remotion-dev/remotion · error · Error

validateWebhookSignature can only be called from Node.JS

Error message

validateWebhookSignature can only be called from Node.JS

What it means

Thrown by validateWebhookSignature() when `require` is undefined at runtime, i.e. the function is being called outside Node.js. The implementation uses CommonJS `require('crypto')` to compute the HMAC, which only exists in Node and not in browser/edge bundlers.

Source

Thrown at packages/lambda-client/src/validate-webhook-signature.ts:27

}: {
	secret: string;
	body: unknown;
	signatureHeader: string;
}) => {
	if (!secret) {
		throw new TypeError(
			"No 'secret' was provided to validateWebhookSignature().",
		);
	}

	if (!body) {
		throw new TypeError(
			"No 'body' was provided to validateWebhookSignature().",
		);
	}

	if (typeof require === 'undefined') {
		throw new Error('validateWebhookSignature can only be called from Node.JS');
	}

	const Crypto = require('crypto');

	const hmac = Crypto.createHmac('sha512', secret);
	const signature = `sha512=${hmac.update(JSON.stringify(body)).digest('hex')}`;

	if (!signatureHeader || signatureHeader === 'NO_SECRET_PROVIDED') {
		throw new Error('No webhook signature was provided');
	}

	if (signatureHeader !== signature) {
		throw new Error('Signatures do not match');
	}
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Only call validateWebhookSignature() from a Node.js runtime (Node Lambda, Express server, Next.js Node route).
  2. In Next.js, mark the importing module with 'use server' or ensure the route runs on the Node.js runtime, not the Edge runtime.
  3. If you must verify webhooks in the browser, do not use this function — verify server-side and trust your own backend.

Example fix

// before (Next.js edge route)
export const runtime = 'edge';
export async function POST(req) {
  await validateWebhookSignature({secret, body: await req.json(), signatureHeader: req.headers.get('X-Remotion-Signature')});
}

// after
export const runtime = 'nodejs';
export async function POST(req) {
  await validateWebhookSignature({secret, body: await req.json(), signatureHeader: req.headers.get('X-Remotion-Signature')});
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the route runs on Node.js — e.g. Next.js:
// export const runtime = 'nodejs';
// Then the call is safe.

Type guard

const isNode = (): boolean => typeof process !== 'undefined' && typeof process.versions?.node === 'string' && typeof require !== 'undefined';

Try / catch

if (typeof require === 'undefined') {
  return res.status(500).send('webhook validation must run in Node.js runtime');
}
validateWebhookSignature({secret, body, signatureHeader});

Prevention

When it happens

Trigger: Calling validateWebhookSignature() from code bundled for the browser (Webpack browser target, Vite client build), a Cloudflare Worker, a Vercel Edge Function, or any environment that shims away `require`.

Common situations: Importing @remotion/lambda-client in a Next.js client component or in a route handler running on the edge runtime; bundling server code with a browser target by mistake.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/d7f5fe4dc6df5715. Report an issue: GitHub.