ComposioHQ/composio · error · ComposioWebhookSignatureVerificationError
No webhook timestamp was provided. Please pass the value of
Error message
No webhook timestamp was provided. Please pass the value of the 'webhook-timestamp' header.
What it means
Thrown when the 'webhook-timestamp' header is missing or empty during webhook signature verification. The timestamp is a component of the signed payload (msgId.timestamp.payload) and is also used for replay-attack tolerance checks, so it is mandatory. The library throws ComposioWebhookSignatureVerificationError rather than guessing a timestamp.
Source
Thrown at ts/packages/core/src/models/Triggers.ts:1253
throw new ComposioWebhookSignatureVerificationError(
"No signature header value was provided. Please pass the value of the 'webhook-signature' header."
);
}
if (secret.length === 0) {
throw new ComposioWebhookSignatureVerificationError(
'No webhook secret was provided. You can find your webhook secret in your Composio dashboard.'
);
}
if (webhookId.length === 0) {
throw new ComposioWebhookSignatureVerificationError(
"No webhook ID was provided. Please pass the value of the 'webhook-id' header."
);
}
if (webhookTimestamp.length === 0) {
throw new ComposioWebhookSignatureVerificationError(
"No webhook timestamp was provided. Please pass the value of the 'webhook-timestamp' header."
);
}
// Parse signature - may have multiple signatures prefixed with version (e.g., "v1,base64sig")
const signatures = signature.split(' ');
const v1Signatures: string[] = [];
for (const sig of signatures) {
const [version, value] = sig.split(',');
if (version === 'v1' && value) {
v1Signatures.push(value);
}
}
if (v1Signatures.length === 0) {
throw new ComposioWebhookSignatureVerificationError(
'No valid v1 signature found in the webhook-signature header. ' +View on GitHub (pinned to 64b1b85502)
Solutions
- Read and pass the 'webhook-timestamp' header exactly as received from Composio
- Verify header names survive any proxy/gateway in front of your handler
- Reject or 400 non-Composio requests before calling verification
- In tests, generate a current Unix-seconds timestamp header value
Example fix
// before
verify({ signature: req.headers['webhook-signature'], webhookId: req.headers['webhook-id'], webhookTimestamp: '' });
// after
verify({
signature: req.headers['webhook-signature'],
webhookId: req.headers['webhook-id'],
webhookTimestamp: req.headers['webhook-timestamp'],
}); Defensive patterns
Strategy: validation
Validate before calling
const ts = req.headers['webhook-timestamp'];
if (typeof ts !== 'string' || ts.length === 0) {
return res.status(400).send('Missing webhook-timestamp header');
} Type guard
const isNonEmptyHeader = (v: unknown): v is string => typeof v === 'string' && v.length > 0;
Try / catch
try { verifyWebhookSignature(...); } catch (e) { if (e instanceof ComposioWebhookSignatureVerificationError) { logger.warn('webhook rejected', e.message); return res.status(400).end(); } throw e; } Prevention
- Validate presence of all three webhook headers before calling verify
- Keep header names lowercase when reading from Node-style request objects
- Log incoming headers in dev to catch proxy stripping
When it happens
Trigger: Calling verifyWebhookSignature with webhookTimestamp set to '' — e.g. the 'webhook-timestamp' header was not read from the request, was renamed by the framework, or the request genuinely lacks it (very old webhook deliveries or non-Composio traffic hitting the endpoint).
Common situations: Header-name casing mismatches (Node lowercases, some platforms do not), proxies stripping custom headers, or sending the webhook endpoint a manually crafted/test payload without the Composio headers.
Related errors
- No webhook ID was provided. Please pass the value of the 'we
- No valid v1 signature found in the webhook-signature header.
- Invalid parameters passed to set webhook subscription
- The signature provided is invalid. Please ensure you are usi
- Invalid webhook timestamp: ${webhookTimestamp}. Expected Uni
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/0db859557f02220e.
Report an issue: GitHub.