Diagnosing and Staging a Google Apps Script Deployment Outage: Access Control and Project Recovery
On 2026-06-02, a critical booking funnel failure took down deposit collection across 11 event pages. This post details the diagnostic approach, root cause identification, and the staged fix—including why the outage happened and how to prevent it in the future.
What Happened: The Symptom
All "Reserve" widget endpoints across the sailjada and queenofsandiego domains returned either 403 Forbidden or 404 Not Found responses. This silently broke the entire deposit ingestion pipeline:
- 10 event pages calling endpoint
https://script.google.com/macros/s/.../44Pme8wCA/execreceived403 - 1 worship page calling a separate endpoint received
404 - No client-side errors logged—the requests failed at the server level
- Impact: every inbound booking and deposit collection attempt was silently failing
Diagnostic Approach
Step 1: Verify HTTP Status Directly
Rather than relying on client reports, we checked both endpoints live:
# Check the primary booking endpoint
curl -I https://script.google.com/macros/s/AKfycbz...44Pme8wCA/exec
# Returns: HTTP 403 Forbidden
# Check the worship endpoint
curl -I https://script.google.com/macros/s/AKfycbz...AFsLWaO3/exec
# Returns: HTTP 404 Not Found
Step 2: Search for Project Metadata
We needed to connect the endpoint URLs to the actual Google Apps Script project. The workflow:
- Searched
/Users/cb/Library/Mobile Documents/com~apple~CloudDocs/jada-ops/for any reference to the Apps Script project name or ID - Checked source repositories for
claspconfig files (`.clasp.json`) to identify which project matched - Located the project ID:
1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5 - Confirmed the display name by reading
appsscript.jsonin the project root
Step 3: Identify Root Cause
The 403 on the primary endpoint indicated access control misconfiguration. The 404 on the worship endpoint suggested a deleted or incorrectly configured deployment. Both pointed to the same underlying issue: the deployment's access settings were not set to "Anyone" (anonymous public access).
This likely occurred after:
- A manual redeploy or project update without resetting access controls
- A permissions audit that tightened access without updating the deployment configuration
- Or a project structure change where the deployment slot was recreated but not properly configured
Technical Details: Why This Matters
Google Apps Script deployments have two independent configuration layers:
- Project ID (
1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5): identifies the source code - Deployment ID (the suffix in the
/execURL, e.g.,44Pme8wCA): points to a specific published version with its own access rules
A common mistake: confusing the project ID with the deployment ID. Knowing the project ID doesn't fix the outage—you must configure the deployment itself.
The Staged Fix
The fix requires exactly one action in the Google Apps Script console:
1. Navigate to script.google.com
2. Open project 1dDpSK8JZda7XUpKIGlyyAX19KLL4JqFjYVtpcunB5ZE3-NMX_9v0lQJ5
3. Go to Deploy → Manage deployments
4. For the active deployment:
- Set "Who has access" to "Anyone"
- Set "Execute as" to your account (the Apps Script owner)
- Click Deploy
Why "Anyone" and "Execute as Me"?
- Who has access = Anyone: allows unauthenticated calls from the public website widgets
- Execute as = [Service Account]: the Apps Script runs with the owner's permissions, not the caller's, ensuring it can access required Google Sheets and write deposits to the backend
This configuration is intentional—the booking widget is genuinely public-facing and must accept anonymous requests from event pages.
Infrastructure Context
The Apps Script project integrates with:
- Google Sheets backend: source of truth for bookings and deposits (not detailed in this post)
- Frontend domains: sailjada.com and queenofsandiego.com, where the Reserve widget HTML is embedded
- Widget delivery: the
/execendpoint serves JSON responses that populate booking forms across 11 event pages
No CloudFront, S3, or Route53 changes were needed for this fix—it's purely a Google Apps Script deployment access control issue.
Key Decisions and Rationale
Why diagnose at the HTTP level first? It isolates whether the problem is in your code, your client-side integration, or the deployment itself. A 403 from Google's servers is unambiguous.
Why not just redeploy the code? Redeploying the code (via clasp push && clasp deploy) creates a new deployment slot with fresh settings. That's overkill and risks changing the deployment URL, which would require updating all 11 event pages. Fixing the access control on the existing deployment is zero-risk and instant.
Why document the project ID separately? In a multi-project environment (e.g., staging vs. production Apps Scripts), the project ID is your source of truth for finding the right project. Deployment IDs can change; project IDs don't.
What's Next
Immediate: Apply the staged fix (flip access to "Anyone") and verify both endpoints return 200 with valid JSON.
Short-term: Add monitoring to both /exec endpoints to catch future 403 or 404 responses before they impact bookings. A simple CloudWatch or external HTTP check every 5 minutes would suffice.
Long-term: Document the deployment access configuration in your runbook so future changes (e.g., updating the Apps Script for a new feature) don't accidentally downgrade permissions.
This outage cost real bookings and deposits. The fix is seconds; the prevention is documentation and monitoring.
```