remotion-dev/remotion · error · Error

Invalid JSON (${type}): ${asString}

Error message

Invalid JSON (${type}): ${asString}

What it means

Thrown by parseJsonOrThrowSource() in @remotion/lambda-client while parsing a streaming Lambda response chunk that could not be JSON.parsed. The function decodes the raw Uint8Array chunk to UTF-8 and attempts JSON.parse; on failure it throws with the offending decoded string and the message type. Lambda streaming (InvokeWithResponseStream) is known to occasionally drop part of the JSON payload; the surrounding code intends to retry on that, but note: the retry trigger compares against 'Cannot parse Lambda response as JSON' (INVALID_JSON_MESSAGE) which does not match this thrown message, so the automatic retry does NOT catch this specific error in the current source.

Source

Thrown at packages/lambda-client/src/call-lambda-streaming.ts:31

	StreamingMessage,
} from '@remotion/serverless-client';
import {
	formatMap,
	makeStreamer,
	messageTypeIdToMessageType,
} from '@remotion/serverless-client';
import {getLambdaClient} from './aws-clients';
import type {AwsRegion} from './regions';

const STREAM_STALL_TIMEOUT = 30000;
const LAMBDA_STREAM_STALL = `AWS did not invoke Lambda in ${STREAM_STALL_TIMEOUT}ms`;

export const parseJsonOrThrowSource = (data: Uint8Array, type: string) => {
	const asString = new TextDecoder('utf-8').decode(data);
	try {
		return JSON.parse(asString);
	} catch {
		throw new Error(`Invalid JSON (${type}): ${asString}`);
	}
};

const invokeStreamOrTimeout = async <Provider extends CloudProvider>({
	region,
	timeoutInTest,
	functionName,
	type,
	payload,
}: {
	region: Provider['region'];
	timeoutInTest: number;
	functionName: string;
	type: string;
	payload: Record<string, unknown>;
}) => {
	const resProm = getLambdaClient(
		region as AwsRegion,

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Retry the render/still at the caller level (wrap renderMediaOnLambda in your own retry).
  2. Upgrade @remotion/lambda and re-deploy the function so client and runtime wire formats match.
  3. Reduce concurrency or stagger renders if you see this alongside throttling.
  4. Inspect the decoded payload snippet in the error message to identify whether it is a partial JSON or an entirely different (error) body.

Example fix

// before
const result = await renderMediaOnLambda({ ... }); // throws Invalid JSON on transient stream drop

// after
async function withRetry<T>(fn: () => Promise<T>, retries = 3) {
  for (let i = 0; i <= retries; i++) {
    try { return await fn(); }
    catch (e) { if (i === retries || !String((e as Error).message).includes('Invalid JSON')) throw e; }
  }
  throw new Error('unreachable');
}
const result = await withRetry(() => renderMediaOnLambda({ ... }));
Defensive patterns

Strategy: retry

Try / catch

async function retryOnBadJson<T>(fn: () => Promise<T>, retries = 3): Promise<T> {
  for (let i = 0; i <= retries; i++) {
    try { return await fn(); }
    catch (e) {
      const msg = String((e as Error).message);
      if (i === retries || !msg.includes('Invalid JSON')) throw e;
    }
  }
  throw new Error('unreachable');
}

Prevention

When it happens

Trigger: A streamed response chunk arrives truncated or with stray bytes (AWS streaming bug), the function returns non-JSON output (e.g. an unexpected error page or partial frame), or a network issue corrupts the stream mid-chunk.

Common situations: High concurrency / throttling causing AWS to truncate the stream; an older Remotion Lambda runtime that emits a different wire format; intermittent AWS networking issues; the renderer function crashing mid-stream and emitting non-JSON.

Understand the failure class

Related errors


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