twentyhq/twenty · critical · Error
Raw request body was not forwarded by the server; cannot ver
Error message
Raw request body was not forwarded by the server; cannot verify the webhook signature
What it means
Webhook signature verification needs the exact raw bytes of the request body, so the route handler requires `routePayload.rawBody` (forwarded via `serverRouteTriggerSettings.forwardedRequestHeaders` and the platform's raw-body forwarding). If `rawBody` is undefined, the handler cannot compute the HMAC and throws. This is a platform/transport misconfiguration: the server is expected to forward the raw body but did not.
Source
Thrown at packages/twenty-apps/public/call-recorder/src/logic-functions/recall-webhook.ts:36
// A thrown error becomes a non-2xx, which makes Svix retry; a returned result dispatches to the target.
export const recallWebhookRouteHandler = (
routePayload: RoutePayload<RecallWebhookBody>,
): RecallWebhookResolverResult => {
const webhookSecret = getApplicationVariableValue(
RECALL_WEBHOOK_SECRET_ENV_VAR_NAME,
);
if (!isNonEmptyString(webhookSecret)) {
throw new Error(
'RECALL_WEBHOOK_SECRET server variable is not set. A server admin must copy it from the Recall webhook endpoint settings and set it on the Call Recorder application registration.',
);
}
const { rawBody } = routePayload;
if (isUndefined(rawBody)) {
throw new Error(
'Raw request body was not forwarded by the server; cannot verify the webhook signature',
);
}
const signatureCheck = verifyRecallWebhookSignature({
rawBody,
headers: routePayload.headers,
secret: webhookSecret,
});
if (!signatureCheck.valid) {
throw new Error(`Invalid webhook signature: ${signatureCheck.error}`);
}
const body = routePayload.body;
if (isUndefined(body) || isNull(body)) {
throw new Error('Webhook payload was empty');View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Ensure the logic function's `serverRouteTriggerSettings` still enables raw-body forwarding (the route declares the svix/webhook headers; confirm the platform also forwards the raw body).
- Check the platform version — if `rawBody` support regressed, roll forward to a version that populates `RoutePayload.rawBody`.
- If a proxy is in the path, configure it to pass the request body through unmodified.
- Until fixed, the route cannot securely verify signatures; do not disable verification as a workaround.
Example fix
// before
const { rawBody } = routePayload;
if (isUndefined(rawBody)) {
throw new Error('Raw request body was not forwarded by the server; cannot verify the webhook signature');
}
// after — log which payload fields arrived to aid platform debugging
const { rawBody } = routePayload;
if (isUndefined(rawBody)) {
console.error('[recall-webhook] rawBody missing; headers=', Object.keys(routePayload.headers ?? {}), 'hasBody=', !isUndefined(routePayload.body));
throw new Error('Raw request body was not forwarded by the server; cannot verify the webhook signature');
} Defensive patterns
Strategy: validation
Validate before calling
// In tests/platform checks, assert RoutePayload carries a rawBody before enabling the route. export const routeSupportsRawBody = (payload: RoutePayload<unknown>): boolean => !isUndefined(payload.rawBody);
Type guard
const hasRawBody = (
p: RoutePayload<unknown>,
): p is RoutePayload<unknown> & { rawBody: string | Buffer } =>
!isUndefined(p.rawBody); Prevention
- Keep `serverRouteTriggerSettings.forwardedRequestHeaders` in sync with what the platform actually forwards, including raw-body forwarding.
- Add a platform regression test that asserts `RoutePayload.rawBody` is populated for webhook routes.
- Do not disable signature verification as a workaround; fix the transport.
- Log which payload fields arrived whenever rawBody is missing to speed platform debugging.
When it happens
Trigger: The logic function platform/routing layer was changed to stop forwarding the raw body (e.g. only forwarding the parsed JSON body), the route trigger settings were edited to drop the raw-body forwarding, or a proxy in front re-encodes the body so the raw bytes are unavailable.
Common situations: A platform upgrade that changed how `RoutePayload.rawBody` is populated; misconfigured `serverRouteTriggerSettings`; a reverse proxy buffering/transforming the request body.
Related errors
- RECALL_WEBHOOK_SECRET server variable is not set. A server a
- Invalid webhook signature: ${signatureCheck.error}
- failed to request artifact import for call recording ${callR
- download failed with status ${response.status}
- download response is missing content-length
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/f63aca4143b8ca4b.
Report an issue: GitHub.