Errors
Index of every error code @hooksentinel/core can throw — HTTP status, retryability, cause, and fix.
Every failure in the verify → deduplicate → parse → handle pipeline produces a HookSentinelError with a stable code, and createWebhookHandler maps that code to an HTTP response automatically unless you override it with onError. This page indexes all eleven codes; each links to a full page with the cause and the concrete fix.
| Code | Status | Retryable | Meaning |
|---|---|---|---|
invalid_signature | 401 | No | Signature present but doesn't match the computed one |
missing_signature_header | 400 | No | Expected signature header wasn't sent |
malformed_signature_header | 400 | No | Signature header present but not in the expected format |
timestamp_out_of_tolerance | 400 | No | Request timestamp outside the allowed window |
missing_raw_body | 500 | No | Body was already parsed before hooksentinel could read raw bytes |
payload_too_large | 413 | No | Body exceeds the configured size limit |
parse_error | 400 | No | Body isn't valid JSON, or doesn't match the provider's shape |
duplicate_event | 200 | No | Event ID already marked processed — not a failure |
idempotency_store_error | 500 | Yes | The idempotency store was unreachable or errored |
handler_error | 500 | Yes | Your onEvent callback threw |
provider_verification_error | 400 | No | A provider-specific check beyond signature/timestamp failed |
How to handle these in code
By default, hooksentinel writes the response for you — you don't need a try/catch around anything. If you want custom logging or a different response shape, use onError:
import { createWebhookHandler, stripe } from '@hooksentinel/core';
import type { HookSentinelError } from '@hooksentinel/core';
const handler = createWebhookHandler({
provider: stripe({ secret: process.env.STRIPE_WEBHOOK_SECRET! }),
onEvent: async (event) => { /* ... */ },
onError: async (error: HookSentinelError, ctx) => {
if (error.code === 'idempotency_store_error') {
logger.error('idempotency store down', { provider: ctx.provider, eventId: ctx.eventId });
}
// return undefined to fall back to hooksentinel's default response for this code
},
});"Retryable" means the provider should redeliver
The retryable column reflects what hooksentinel tells the provider by way of the HTTP status — a 5xx tells Stripe, GitHub, etc. to retry the delivery later; a 4xx tells them not to bother, because retrying the exact same request will fail the same way. Two codes (idempotency_store_error, handler_error) are retryable because the failure is transient or on your side, not a property of the request itself.
Last updated on
API Reference
Core types and exported functions from @hooksentinel/core, its provider, store, framework, and testing subpaths.
invalid_signature
hooksentinel error invalid_signature — the request's signature header didn't match the signature computed from the body and secret. Common causes and the fix.