{"record":{"id":"cdda0d1aa0eea288","repo":"ComposioHQ/composio","slug":"no-webhook-id-was-provided-please-pass-the-value","errorCode":null,"errorMessage":"No webhook ID was provided. Please pass the value of the 'webhook-id' header.","messagePattern":"No webhook ID was provided\\. Please pass the value of the 'webhook-id' header\\.","errorType":"exception","errorClass":"ComposioWebhookSignatureVerificationError","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/models/Triggers.ts","lineNumber":1247,"sourceCode":"  ): Promise<void> {\n    if (payload.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError('No webhook payload was provided.');\n    }\n\n    if (signature.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        \"No signature header value was provided. Please pass the value of the 'webhook-signature' header.\"\n      );\n    }\n\n    if (secret.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        'No webhook secret was provided. You can find your webhook secret in your Composio dashboard.'\n      );\n    }\n\n    if (webhookId.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        \"No webhook ID was provided. Please pass the value of the 'webhook-id' header.\"\n      );\n    }\n\n    if (webhookTimestamp.length === 0) {\n      throw new ComposioWebhookSignatureVerificationError(\n        \"No webhook timestamp was provided. Please pass the value of the 'webhook-timestamp' header.\"\n      );\n    }\n\n    // Parse signature - may have multiple signatures prefixed with version (e.g., \"v1,base64sig\")\n    const signatures = signature.split(' ');\n    const v1Signatures: string[] = [];\n\n    for (const sig of signatures) {\n      const [version, value] = sig.split(',');\n      if (version === 'v1' && value) {\n        v1Signatures.push(value);","sourceCodeStart":1229,"sourceCodeEnd":1265,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/models/Triggers.ts#L1229-L1265","documentation":"Thrown by Composio's webhook signature verification when the 'webhook-id' header is missing or empty. Verification requires the webhook ID (msgId) because it is part of the signed payload (msgId.timestamp.payload), so without it the HMAC cannot be computed. The library throws ComposioWebhookSignatureVerificationError instead of silently accepting an unverifiable request.","triggerScenarios":"Calling composio.triggers.verifyWebhookSignature(payload, signatureHeader, {secret, webhookId, webhookTimestamp}) (or a verify/tolerate API that reads request headers) where webhookId is '' — typically because the 'webhook-id' header was not forwarded from the incoming request to the verification call.","commonSituations":"Frameworks that strip or rename custom headers (proxies, API gateways, AWS API Gateway header normalization), passing headers in the wrong order or with wrong names, or test code that only supplies 'webhook-signature' and 'webhook-timestamp'.","solutions":["Forward the exact 'webhook-id' header from the webhook request into the verification call's webhookId option","Check that your proxy/gateway does not strip custom webhook-* headers","Log all incoming webhook-* headers in a debug route to confirm what arrives","Ensure test harnesses send all three headers: webhook-id, webhook-timestamp, webhook-signature"],"exampleFix":"// before\nawait composio.triggers.verifyWebhookSignature(rawBody, sig, { secret, webhookId: req.headers['webhook_id'] ?? '', webhookTimestamp: req.headers['webhook-timestamp'] });\n// after\nawait composio.triggers.verifyWebhookSignature(rawBody, sig, {\n  secret,\n  webhookId: req.headers['webhook-id'] as string,\n  webhookTimestamp: req.headers['webhook-timestamp'] as string,\n});","handlingStrategy":"validation","validationCode":"const h = req.headers;\nif (!h['webhook-id'] || !h['webhook-timestamp'] || !h['webhook-signature']) {\n  return res.status(400).send('Missing webhook headers');\n}","typeGuard":"const hasWebhookHeaders = (h: Record<string, unknown>): boolean =>\n  typeof h['webhook-id'] === 'string' && (h['webhook-id'] as string).length > 0;","tryCatchPattern":"try { verifyWebhookSignature(...); } catch (e) { if (e instanceof ComposioWebhookSignatureVerificationError) return res.status(400).end(); throw e; }","preventionTips":["Forward all webhook-* headers verbatim to the SDK","Add a 400 guard for missing webhook-* headers before verification","Cover the webhook route with integration tests that replay real header sets"],"tags":["webhook","signature-verification","missing-header","typescript"],"backgroundTag":"webhook-signature-verification-failed","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}