Incident pattern

Stripe webhook signature verification failed on Bubble

Stripe's dashboard shows webhook deliveries failing or erroring, payments complete in Stripe, but orders, subscriptions, or access never appear in your Bubble app.

  • Bubble
  • Webhooks
  • Checkout & payments

Root cause, in plain English

Stripe signs every webhook with a secret that belongs to one specific endpoint. Bubble rejects the event when verification runs against the wrong secret — usually because the live endpoint was created at launch while the workflow still holds the test endpoint's whsec_ value, the secret was rotated, or the endpoint URL still points at Bubble's /version-test branch, so live events never reach the workflow that holds the right secret.

How to fix it

  1. Open Stripe → Developers → Webhooks (or Workbench) and read the actual delivery error on the failing endpoint — signature failures and connection failures look identical from inside Bubble.

  2. Confirm the live endpoint URL is your deployed Bubble workflow URL: no /version-test segment and not the /initialize URL Bubble used during setup.

  3. Click "Reveal" on that exact endpoint's signing secret (whsec_…) while in live mode, and paste it into the Bubble workflow or plugin field that verifies signatures. Test and live endpoints have different secrets.

  4. If the workflow modifies the request before verifying (re-encoding the body, trimming fields), verify against the raw payload instead — the signature covers the exact bytes Stripe sent.

  5. Use Stripe's "Resend" on a failed delivery to confirm the fix, then replay the events that failed while the secret was wrong so missed orders get processed.

Go deeper: read the full guide · copy the open-source health-check recipe.

How Nightlamp detects this automatically

  • API canary
  • Browser journey
  • HTTP status

An api_canary posts a signed synthetic event to your webhook endpoint on a schedule and alerts the moment it stops returning the expected 2xx — catching secret rotations and URL drift before a real checkout fails. A browser_journey walks the live checkout path, and an http_status check watches the workflow endpoint itself.

Catch this before your customers do

Nightlamp runs these checks continuously against your live app and sends a plain-English diagnosis — not a wall of logs — the moment this pattern shows up.

Frequently asked questions

Why does the webhook work in test mode but fail in live mode?
Test and live modes are separate environments in Stripe with separate endpoints and separate signing secrets. A workflow that verifies with the test secret will reject every live event. Create a dedicated live endpoint and store its own whsec_ value.
Can I just disable signature verification to get unblocked?
You can, but then anyone who discovers the URL can post fake "payment succeeded" events to your app. Treat disabling verification as a five-minute diagnostic step at most, never a fix.
Stripe says delivery succeeded — is this still a signature problem?
No. A 2xx in Stripe's delivery log means your endpoint accepted the event. If the order still didn't appear, the failure is inside the workflow itself — see the "webhook returns 200 but nothing happens" pattern.
Do I need to re-process the events that failed?
Yes. Stripe retries failed deliveries with backoff for up to about three days, then stops. Anything older must be resent manually from the Stripe dashboard or reconciled from the Payments list.

Newsletter

Get new incident patterns as we publish them

One email when new failure patterns, fixes, and monitoring recipes for no-code and AI-built apps land. No fluff, unsubscribe any time.

Double opt-in. One-click unsubscribe. No spam, ever.