## TL;DR

Verify the token against the same JWT secret that signed it. Supabase edge functions check signatures with the project's JWT secret, so if the function uses the wrong secret, a rotated secret, or the anon key instead, every signature check fails. Align the secret and the error goes away.

```text
supabase edge function error: JWT signature does not match when calling external API
```

## Steps

1. Log the token's decoded header and payload (never log the full token) and note the issuer and key id claims. Expected: you can see which project and key the token claims to come from.

2. In the Supabase dashboard, open the project settings and confirm the current JWT secret. Expected: you have the canonical secret the project signs tokens with.

3. Compare: check which value your edge function reads for verification (its environment config). Expected: you find whether the function points at the right secret or something else, like the anon key or a stale copy.

4. If the project secret was rotated or the function caches an old one, update the function's config to the current JWT secret and redeploy. Expected: the deployed function holds the current secret.

5. Check the token itself is complete: not truncated in transit, no whitespace appended, and signed with HS256. Expected: the token parses cleanly as three dot-separated parts.

6. Retry the edge function call. Expected: the signature verifies and the call proceeds past auth.

## Use this when

- A Supabase edge function returns exactly "JWT signature does not match".
- The failure started right after a secret rotation or a redeploy.
- The same token verifies fine in one environment but not another.

## Not for this skill when

- The token is expired (that is a different error, fix the expiry).
- The failure is a row-level-security policy denial, not a signature check.
- The JWT comes from a non-Supabase issuer with its own key setup.

## Variant phrasings

- Supabase edge function JWT signature mismatch
- Supabase function JWT verification failed
- JWT signature does not match Supabase edge function

## Why it happens

A JWT signature only verifies against the exact secret that signed it. Generated clients often wire the wrong value into the edge function: the public anon key instead of the JWT secret, a secret copied from the wrong project, or a stale copy left over after the dashboard secret was rotated. Any of those makes every signature check fail even though the token itself is fine.

## Edge cases

- Rotating the JWT secret in the dashboard invalidates all outstanding tokens; expect a short window of failures while clients pick up new tokens.
- The anon key and the JWT secret are different values; swapping them is the most common wiring mistake.
- Tokens truncated by logging or URL handling fail signature checks even with the right secret, so check token integrity before blaming the secret.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_q5OVHMRv8_iZ1DS_tFMl6w
