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

  1. 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).
  2. Check the platform version — if `rawBody` support regressed, roll forward to a version that populates `RoutePayload.rawBody`.
  3. If a proxy is in the path, configure it to pass the request body through unmodified.
  4. 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

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


AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12). Data as JSON: /api/errors/f63aca4143b8ca4b. Report an issue: GitHub.