TanstackTemplate
Operations

Deploy Troubleshooting

Start every failure by identifying which gate failed. A source preflight, a Wrangler publish, a D1 migration, a custom-domain attach, a deploy health smoke, and a real conversion smoke prove different things.

Preflight Passed But Wrangler Failed

pnpm preflight:cloudflare-token -- --environment staging proves that the token is active, can list Workers scripts, can query the configured D1 database, and can list configured R2 buckets. It deliberately leaves Worker publication as DEFER because only wrangler deploy proves publish permission.

If preflight passes but wrangler deploy fails:

  1. Confirm the build and deploy used the same environment:

    RELEASE_COMMIT_SHA="$(git rev-parse HEAD)" CLOUDFLARE_ENV=staging pnpm --filter <web-package> build
    CLOUDFLARE_ENV=staging pnpm --filter <web-package> exec wrangler deploy
  2. Inspect the flattened deploy artifact, not only source config:

    pnpm assert:worker-deploy-target -- --environment staging
  3. Recheck token scope. The token still needs Worker publish permission, and custom-domain deploys may also need route or zone permission.

  4. Rerun with Cloudflare diagnostics if the error is opaque:

    WRANGLER_LOG=debug CLOUDFLARE_ENV=staging pnpm --filter <web-package> exec wrangler deploy
  5. If GitHub failed but local deploy works, rotate and verify the GitHub CLOUDFLARE_API_TOKEN secret before dispatching again:

    export CLOUDFLARE_ACCOUNT_ID=<cloudflare-account-id>
    pnpm secrets:sync-github -- --secret CLOUDFLARE_API_TOKEN --force --verify-cloudflare-token --account-id "$CLOUDFLARE_ACCOUNT_ID"
    pnpm secrets:sync-github -- --secret CLOUDFLARE_API_TOKEN --force --verify-cloudflare-token --yes --account-id "$CLOUDFLARE_ACCOUNT_ID" --receipt-output artifacts/secret-rotation/cloudflare-token-receipt.json

D1 7403

Treat D1 7403 or nearby "database not found / not accessible" failures as an account, database ID, binding, or permission mismatch until proven otherwise. This usually appears during remote migration or preflight, not during local SQLite-like development.

Check the selected environment first:

pnpm doctor:config -- --environment staging
pnpm preflight:cloudflare-token -- --environment staging
pnpm --filter <web-package> exec wrangler d1 list

Then compare the visible database to apps/web/wrangler.jsonc:

  • env.staging.d1_databases[].binding should be CONVERSION_DB.

  • database_name should be the staging database name for this product.

  • database_id should be the UUID returned by wrangler d1 list in the same account.

  • The command should apply migrations through the binding:

    pnpm --filter <web-package> exec wrangler d1 migrations apply CONVERSION_DB --env staging --remote

Do not copy the source template D1 IDs into a downstream Cloudflare account. Create the downstream database, paste its returned ID into the staging target, and rerun preflight.

Workers Routes 10000 Or Custom Domain Failure

Error code 10000 around Workers Routes or custom-domain attachment is usually an authentication or authorization failure for the route operation. It can also show up when the hostname is not in an active zone owned by the account, or when an existing DNS record conflicts with a custom-domain attach.

For the first downstream proof, use the quick workers.dev path and remove custom-domain routing from the staging target. That reduces the required token surface to account-level Worker, D1, and R2 permissions.

For the advanced custom-domain path:

  1. Confirm the zone is active in the same Cloudflare account used by CLOUDFLARE_ACCOUNT_ID.

  2. Confirm the hostname has no conflicting DNS record.

  3. Confirm the route entry uses the custom-domain shape:

    {
      "pattern": "app.example.com",
      "custom_domain": true
    }
  4. Use an account-scoped token that can deploy Workers and manage Workers routes/custom domains for the selected zone.

  5. If the route is not essential for this proof, remove the route and deploy to https://<worker-name>.<account-subdomain>.workers.dev first.

Conversion Smoke Token Mismatch

The canonical demo-auth conversion smoke sends x-demo-auth-token. The Worker accepts it only when it matches the Worker-side CONVERSION_DEMO_AUTH_TOKEN secret.

Symptoms include 401 auth_required, conversion smoke failure before upload work, or a smoke that passes health but cannot submit a real conversion.

Fix the secret on both sides:

export CONVERSION_DEMO_AUTH_TOKEN=<same-token-configured-on-staging-worker>
printf '%s' "$CONVERSION_DEMO_AUTH_TOKEN" | pnpm --filter <web-package> exec wrangler secret put CONVERSION_DEMO_AUTH_TOKEN --env staging
pnpm secrets:sync-github -- --secret CONVERSION_DEMO_AUTH_TOKEN
pnpm secrets:sync-github -- --secret CONVERSION_DEMO_AUTH_TOKEN --yes

Then smoke the same Worker URL:

SMOKE_BASE_URL=https://<target-worker-url> \
SMOKE_DEMO_AUTH_TOKEN="$CONVERSION_DEMO_AUTH_TOKEN" \
SMOKE_EXPECT_RELEASE_COMMIT_SHA="$(git rev-parse HEAD)" \
pnpm smoke:staging

Cloudflare does not let you read the existing Worker secret value back. If in doubt, overwrite it with the intended value and rerun smoke.

Health Smoke Commit Mismatch

Deploy health smoke and staging smoke compare the expected commit to /api/health release metadata. A mismatch means the smoke is not proving the commit you think it is proving.

Common causes:

  • The Worker was built without RELEASE_COMMIT_SHA.
  • The build used the wrong CLOUDFLARE_ENV.
  • The smoke is pointed at an old custom domain, canary URL, or workers.dev URL.
  • The deploy finished, but the smoke reached the previous Worker version.
  • A downloaded smoke artifact belongs to an older workflow run.

Diagnose with:

curl -s https://<target-worker-url>/api/health
git rev-parse HEAD

Then rebuild, deploy, and smoke the same target:

export CURRENT_SHA="$(git rev-parse HEAD)"
RELEASE_COMMIT_SHA="$CURRENT_SHA" CLOUDFLARE_ENV=staging pnpm --filter <web-package> build
CLOUDFLARE_ENV=staging pnpm --filter <web-package> exec wrangler deploy
DEPLOY_HEALTH_EXPECT_RELEASE_COMMIT_SHA="$CURRENT_SHA" pnpm smoke:deploy-health -- --environment staging --base-url https://<target-worker-url>

Do not reuse release evidence from a mismatched commit. Generate or download new current-commit smoke evidence after the deployed health payload reports the expected SHA.

On this page