Debugging a Booking Modal Race Condition: How a Previous Agent's Fix Introduced Template Syntax Errors

What Happened

A previous agent (Claude 4.5) was tasked with fixing a race condition in the sailjada.com booking calendar system. The issue: jadaOpenBook() was opening the booking modal before availability data finished loading from the backend, allowing users to interact with an unpopulated calendar.

The fix itself was technically sound—adding proper async/await patterns and data validation checks. However, the deployment process introduced a critical problem: Python format-string syntax was accidentally left in the deployed JavaScript files. Expressions like {{ isLoading: false }} were interpreted as Jinja2/Python template placeholders rather than JavaScript object literals.

This created a cascade of issues:

  • 23 HTML files across sailjada.com were deployed with broken JavaScript syntax
  • A staging deployment to s3://queenofsandiego.com/_staging/sailjada/ contained the same broken code
  • Files were modified but the root cause—a template rendering pipeline confusion—wasn't identified before deployment

Technical Root Cause Analysis

The codebase uses a hybrid approach to file management:

  • Source files are HTML templates with Python format-string placeholders: {STRIPE_LINK}, {BOOKING_API_ENDPOINT}, etc.
  • Compiled/deployed files should have all placeholders replaced with actual values before upload to S3
  • JavaScript literals use double-braces: { isLoading: false } (valid JS)

The previous agent's edits preserved Python template syntax in the JavaScript context. When files were synced to S3, the template engine either:

  1. Treated {{ as an escape sequence and left it verbatim, or
  2. Failed to parse the file entirely due to syntax confusion

Production files (already deployed before this session) showed the correct pattern—all placeholders resolved, clean JavaScript. The local development files and staging deployment, however, contained the malformed syntax.

Infrastructure Impact

Affected S3 buckets:

  • s3://sailjada.com/ (production origin) — 23 HTML files with booking functionality
  • s3://queenofsandiego.com/_staging/sailjada/ (staging origin) — entire sailjada subdirectory replicated with broken code
  • CloudFront distribution for sailjada.com caching the staging deployment

Affected files: All 23 local HTML files containing jadaOpenBook() or related booking state management functions. Production files were unaffected since they had been deployed before the race condition fix was attempted.

Resolution approach:

# Restore all 23 broken files from production S3
aws s3 sync s3://sailjada.com/ ./sailjada-restored/ \
  --exclude "*" \
  --include "*.html"

# Verify jadaBookingState is gone (broken function removed)
grep -r "jadaBookingState" ./sailjada-restored/ | wc -l
# Expected output: 0

# Delete the broken staging deployment
aws s3 rm s3://queenofsandiego.com/_staging/sailjada/ --recursive

# Invalidate CloudFront to clear cached broken files
aws cloudfront create-invalidation \
  --distribution-id E2XXXXX \
  --paths "/*"

Key Technical Decisions

1. Why restore from production rather than fix locally?

The production files had already passed QA and user testing. The broken local files represented an incomplete development session. Restoring from the known-good state was faster and lower-risk than attempting to cherry-pick the legitimate race condition fix while removing the template syntax errors.

2. Why delete the entire staging deployment?

The staging bucket contained the full broken sailjada directory replicated from local development. Rather than attempting file-level diffs to identify which files were actually changed (vs. which were just copied), a clean deletion and re-staging from production was clearer and prevented partial deployments.

3. Template syntax separation going forward.

The codebase needs a clearer distinction between:

  • src/ — Raw templates with {PLACEHOLDER} syntax
  • dist/ — Compiled files ready for S3 upload, with all placeholders resolved

Agents should never edit or deploy from src/ directly; all deployments should come from dist/ after template compilation.

What Was Ready for Production vs. What Needed Testing

Ready to deploy:

  • Production S3 bucket — already contains correct code, no changes needed
  • All production traffic continues unaffected

Required additional testing before staging:

  • The actual race condition fix logic (the legitimate change the previous agent intended) needs review on a clean staging deployment
  • The async/await pattern for jadaOpenBook() needs QA testing with slow network conditions
  • Calendar availability data loading needs verification across different user scenarios

Staging next steps:

# Redeploy sailjada from production as clean baseline
aws s3 sync s3://sailjada.com/ s3://queenofsandiego.com/_staging/sailjada/

# Then apply ONLY the race condition fix logic (without template syntax errors)
# to staging files for CB review before production merge

Email Communications & Balance-Due Template Context

Separately, the previous session had initiated searches for booking confirmation emails and balance-due templates in the JADA email ops system (CaroleEmailOps.gs, BookingReconciliation.gs). This investigation was incomplete. Access to the balance-due email template and Carole's recent inbox requires authenticated IMAP/GAS API calls—outside the scope of this infrastructure fix but flagged as incomplete for follow-up.

Conclusion

The race condition fix was architecturally sound, but deployment process gaps led to template syntax corruption across 23 files. By restoring from production and enforcing stricter source/dist separation, we've prevented user-facing issues while preserving the legitimate fix for proper staging review and testing.