Troubleshooting

Trace symptoms to configuration, data, and execution stages to troubleshoot local development, authentication, payments, background jobs, and deployment.

When something goes wrong, identify which step did not complete before deciding what to change. This chapter contains six articles organized around the current default template's workflows. Problems in the same workflow are covered together, so you do not have to keep switching between authentication, email, and OAuth, or between payments and webhooks.

Find an article by symptom

SymptomArticleWhat to check
Installation, startup, or build failures, or content that does not updateLocal development and buildsNode.js, initialization, configuration validation, content generation
Missing tables or data, migration failures, or constraint conflictsDatabases and migrationsTarget database, existing schema, migration records
Sign-in redirects, verification code or email issues, or failed Google or GitHub sign-inSign-in, email, and OAuthCookies, verification status, email delivery mode, callback configuration
Checkout failures, access missing after payment, or webhook errorsPayments and webhooksStripe connections, event ledger, transactions, entitlement grants
Queue messages produce no results, recurring tasks do not run, or analytics has no dataBackground jobs and analyticsConsumer dispatch, Events, Commands, Cron
Interrupted first deployment, missing resources, domain issues, or stale production contentDeployment, resources, and domainsRelease stage, resource ownership, runtime configuration, content synchronization

1. Establish reproducible conditions

Record the environment, code version, URL, time of the operation, and shortest steps to reproduce the issue. For example, “In production, a regular account purchased the yearly plan. Stripe shows the payment as complete, but the product is still unavailable after refreshing the product page” is easier to investigate than “Payments are broken.”

Inspect local and production environments separately. Missing records in local D1 do not show whether a production payment was saved. Likewise, changing local .env does not let you test that change in production.

EvidenceWhere to find itPurpose
Request method, path, HTTP status, and response bodyBrowser Network panelDistinguish a request that was never sent from an endpoint rejection or server exception
First exception, request time, and correlation IDLocal terminal, Worker logsIdentify the failed step and correlate subsequent processing
Event ID, Checkout ID, and internal execution IDPayment platform and application logsTrace the same business operation without guessing based on similar timestamps
Configuration keys, resource names, and IDsconfig/, wrangler.jsoncConfirm which targets the application is using
Table schemas, statuses, and record timestampsRead-only queries against the relevant D1 databaseDetermine which steps have been persisted

An API's code may be a numeric result code, part of a third-party protocol, or absent altogether. Look up numeric codes in src/errors.ts. Do not assume every response is a complete APIResponse<T>.

Redact cookies, tokens, secrets, verification codes, and recipient information before sharing troubleshooting details. Local email previews include message bodies, so check terminal output before copying it as well.

2. Check diagnostics, then verify the workflow

From the root of the initialized project, choose the check for your environment:

# Local configuration
npm run doctor
# Production configuration and Cloudflare account access
npm run doctor:remote

doctor checks configuration, variables, binding names, database directories, and related settings. doctor:remote reads .env.production and also checks that remote resource IDs are filled in and that the current identity can access the configured account.

These commands do not fully test your production services. Passing the checks does not prove that every resource exists, that Resend delivered an email, that Stripe completed a callback, or that a Queue task ran. Disabled optional services may produce notices or warnings. Evaluate them in the context of the feature you are testing.

3. Continue from the last successful step

A typical payment flow is:

Create Checkout → The user pays → Verify the webhook signature
→ Update payment records → Create a business Event → Execute Commands → Grant user access

If the correct payment event has arrived, inspect payment records and access processing next. There is no need to keep changing the Checkout page. If no callback has arrived, address the callback URL, secret, and delivery issues first.

The same applies to background jobs. Completion of queue.send(), message acknowledgment, Command success, and completion by an external service are separate stages. Verify each one separately.

4. Verify the fix

Repeat the same reproduction case and check related failure scenarios. For example, after correcting a plan mapping, check both that a new payment grants access and that duplicate callbacks do not create duplicate grants.

After code changes, run the project's npm run verify. After changing configuration or provider settings, also test the relevant workflow. Successful compilation does not prove that an external service is available.

Preserve evidence of the failure

Do not reset the production database, delete payment event records, or change SAAS_SECRET just to make an error disappear. Locate the failure before choosing a recovery method. Resetting a database deletes its data, and changing the master secret may make existing encrypted data unreadable.

Common errors

Error or messageNext step
Configuration validation failed at startupInspect the reported field path and check configuration values and references
no such tableCheck the D1 binding, environment, and migration status
Binding ... not foundCheck the actual bindings. Generating types does not create resources
redirect_uri_mismatchCompare the full callback URLs configured on the third-party platform and used by the application
emailSendTooOftenCheck email sending quotas and duplicate submissions. Do not keep retrying
PAYMENT_NOT_CONFIGUREDCheck the current Worker's Stripe connection and keys
WEBHOOK_BUSYInspect the event's processing lease and logs. Do not delete the ledger
paymentsProductAlreadyPurchasedCheck the plan's repeat-purchase rules and existing purchase records
Command outcome needs manual reviewCheck external effects first to avoid duplicate sends or grants
401, 403, 429Use the response body to distinguish session, permission, origin validation, and rate limiting issues

For exact field definitions, see the reference. To complete a release from the beginning, see deployment.