Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?

Node.js · updated 2026-11-11

Thrown by stripe.webhooks.constructEvent() (a StripeSignatureVerificationError, which logs as Error) in your webhook route when the stripe-signature header does not match the body you passed in. It also covers the wrong signing secret. Two related messages come from the same check: a parsed object instead of the raw body ("Webhook payload must be provided as a string or a Buffer"), and a missing header ("No stripe-signature header value was provided").

Error: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
 If a webhook request is being forwarded by a third-party tool, ensure that the exact request body, including JSON formatting and new line style, is preserved.

Learn more about webhook signing and explore webhook integration examples for various frameworks at https://docs.stripe.com/webhooks/signature

Quick fix

Give constructEvent the exact bytes Stripe sent. In Express, mount express.raw({ type: 'application/json' }) on the webhook route, before any app-wide express.json(). In a Next.js route handler, read await request.text(). Then check the secret: each webhook endpoint (and the Stripe CLI) has its own whsec_ value, and test and live mode differ.

  1. Read which message you got: "No signatures found" means the body or the secret is wrong; "must be provided as a string or a Buffer" means a JSON parser ran first; "No stripe-signature header" means the header never reached your code.
  2. Express: use express.raw({ type: 'application/json' }) on the webhook route and register it before app.use(express.json()).
  3. Next.js App Router: const body = await request.text(); never request.json() before verifying.
  4. Use the signing secret of this exact endpoint and mode. stripe listen prints its own whsec_ for local testing.
  5. Check proxies and middleware that rewrite bodies (pretty-printing, re-serializing, gzip handling).
typescript
// Express: the webhook route gets the raw body; everything else can use JSON
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => {
  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature']!, process.env.STRIPE_WEBHOOK_SECRET!);
  } catch (err) {
    return res.status(400).send(`Webhook signature check failed: ${(err as Error).message}`);
  }
  // handle event.type ...
  res.json({ received: true });
});
app.use(express.json()); // after the webhook route
Fix it with your coding agent

Paste this into Claude Code, Cursor or Codex in the project that throws it. The agent reads this guide in plain text and applies the fix that matches your stack.

prompttext
Read https://runheed.com/errors/stripe-no-signatures-found-matching-expected-signature.md and fix this error in this project.

Why it happens

A JSON parser ran first

app.use(express.json()) or a framework body parser turned the body into an object; re-serializing it never matches the signed bytes.

Wrong signing secret

The secret belongs to another endpoint, to the Stripe CLI, or to the other mode (test vs live).

Body changed in transit

Middleware, a proxy or a framework adapter rewrote the body (formatting, encoding) before your handler saw it.

Header stripped

A proxy or the framework dropped the stripe-signature header, so constructEvent has nothing to check.

Other fixes

  • Answer 400 on a failed check so Stripe retries later; don't answer 200 and drop the event.
  • Report these failures to your error tracker with the endpoint path: a burst right after a deploy usually means a middleware order change.

Same error, other wording

  • Webhook payload must be provided as a string or a Buffer instance representing the _raw_ request body. Payload was provided as a parsed JavaScript object instead.
  • No stripe-signature header value was provided.
  • stripe._error.SignatureVerificationError: No signatures found matching the expected signature for payload

Let your coding agent catch the next one

Runheed records this error in production with the stack trace, the breadcrumbs before it and, when you set it, the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:

> Find the Stripe webhook signature errors, check how the webhook route reads its body and which secret it uses, and fix the route so it verifies the raw body with the right endpoint secret.

Setup for Node.js and Express or Vercel Functions, then have your agent fix and resolve it.

Related errors

More in Network and HTTP

References: Stripe docs: check webhook signatures, stripe-node source: webhook signature verification

Spotted a mistake? Email hello@greatwork.company. About Runheed.