remotion-dev/remotion · error · Error

frame must be an integer.

Error message

frame must be an integer.

What it means

This error is thrown by a Remotion Studio MCP tool handler when the `frame` argument passed to a frame-related tool (e.g. seek/set-frame) is not a JavaScript number or not an integer. The tool schema declares `frame` as required, but MCP clients can send values that arrive as strings or floats, so the handler re-validates at runtime. It exists to prevent seeking to a non-integer frame, which has no meaning in Remotion's timeline.

Source

Thrown at packages/studio/src/components/WebMcp.tsx:1771

					title: 'Seek Studio timeline',
					description:
						'Seek the current Remotion Studio composition to a frame. Frames past the end of the composition are clamped to the final frame.',
					inputSchema: {
						type: 'object',
						properties: {
							frame: {
								type: 'integer',
								minimum: 0,
								description: 'The zero-based frame to seek to.',
							},
						},
						required: ['frame'],
						additionalProperties: false,
					},
					annotations: {readOnlyHint: false},
					execute: ({frame}) => {
						if (typeof frame !== 'number' || !Number.isInteger(frame)) {
							throw new Error('frame must be an integer.');
						}

						const compositionId = currentCompositionRef.current;
						if (compositionId === null) {
							throw new Error('No composition is currently selected.');
						}

						const currentFrame = Math.min(
							Math.max(0, frame),
							getCurrentDuration() - 1,
						);
						seek(currentFrame);
						return Promise.resolve({
							currentFrame,
							currentContent: currentContentRef.current,
						});
					},
				},

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Ensure the MCP client sends frame as a JSON integer, not a string: pass 30, not "30"
  2. Round or floor computed frame values before calling the tool: Math.floor(time * fps)
  3. Verify the tool call arguments against the tool's input schema (frame is required, type integer) before invoking
  4. Check for accidental null/undefined when the frame value is derived from an optional variable

Example fix

// before
await mcp.callTool('seekToFrame', {frame: "30"}); // string
await mcp.callTool('seekToFrame', {frame: time * fps}); // may be fractional

// after
await mcp.callTool('seekToFrame', {frame: Math.floor(time * fps)});
Defensive patterns

Strategy: validation

Validate before calling

const frame = Number(rawFrame);
if (!Number.isInteger(frame)) {
  // don't call the tool; fix the value first
  throw new TypeError(`Expected integer frame, got ${JSON.stringify(rawFrame)}`);
}
await mcp.callTool('seekToFrame', {frame});

Type guard

const isIntegerFrame = (v: unknown): v is number =>
  typeof v === 'number' && Number.isInteger(v);

Try / catch

try {
  await mcp.callTool('seekToFrame', {frame});
} catch (err) {
  if (err instanceof Error && err.message === 'frame must be an integer.') {
    // coerce/round and retry once
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling a Studio WebMCP frame tool (e.g. via an MCP client like Claude) with frame sent as a string ("30" instead of 30), a float (29.5), null/undefined, or a value that JSON-parses to a non-number. Also occurs when a client library serializes integers as strings.

Common situations: MCP client implementations that don't coerce tool arguments to the declared JSON schema types; agent prompts that quote numbers; hand-rolled MCP requests that send frame as text; time-to-frame conversions producing fractional frames.

Related errors


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-08-28). Data as JSON: /api/errors/ccf73acbf9fb555e. Report an issue: GitHub.