remotion-dev/remotion · error · Error
A value which is not a Zod schema was passed to `schema`
Error message
A value which is not a Zod schema was passed to `schema`
What it means
When the Render Modal's schema editor resolves a composition's `schema` prop, `resolveCompositionSchema()` accepts any explicit value but verifies it duck-types as Zod (`safeParse` must be a function, packages/studio/src/components/RenderModal/SchemaEditor/infer-zod-schema-from-value.ts:127). If you passed something truthy that is not a Zod schema instance — a plain object, a schema builder like `z.object` un-applied, or a Zod namespace — Studio throws this error instead of rendering the props editor.
Source
Thrown at packages/studio/src/components/RenderModal/SchemaEditor/infer-zod-schema-from-value.ts:129
explicitSchema,
defaultProps,
z,
zodTypes,
}: {
readonly explicitSchema: unknown;
readonly defaultProps: Record<string, unknown>;
readonly z: ZodNamespace | null;
readonly zodTypes: ZodTypesType | null;
}): ResolvedCompositionSchema {
if (!z) {
return 'no-zod';
}
if (explicitSchema) {
if (
typeof (explicitSchema as {safeParse?: unknown}).safeParse !== 'function'
) {
throw new Error(
'A value which is not a Zod schema was passed to `schema`',
);
}
return explicitSchema as AnyZodSchema;
}
if (Object.keys(defaultProps).length === 0) {
return 'no-schema';
}
return inferZodSchemaFromValue({
value: defaultProps,
z,
zodTypes,
path: [],
});
}View on GitHub (pinned to 10db9de073)
Solutions
- Pass an actual Zod schema: wrap fields with `z.object({...})` and pass the result (`schema={z.object({title: z.string()})}`).
- Sanity-check before assigning: `typeof schema.safeParse === 'function'` must hold.
- If using a custom/aliased zod instance or version (zod/v4, zod-mini), make sure the value passed is a schema instance from that same library, not a config object or namespace.
Example fix
// before
<Composition schema={{title: z.string(), count: z.number()}} ... />
// after
<Composition schema={z.object({title: z.string(), count: z.number()})} ... /> Defensive patterns
Strategy: type-guard
Validate before calling
import {z} from 'zod';
const schemaValue = z.object({title: z.string()});
if (typeof schemaValue.safeParse !== 'function') {
throw new TypeError('schema must be a Zod schema instance');
}
// safe to pass to <Composition schema={schemaValue}> Type guard
import type {ZodType} from 'zod';
const isZodSchema = (value: unknown): value is ZodType =>
typeof value === 'object' &&
value !== null &&
typeof (value as {safeParse?: unknown}).safeParse === 'function'; Prevention
- Always pass the result of a Zod builder (`z.object({...})`), never the factory itself (`z.object`) or a plain fields object.
- If you centralize schemas, export Zod instances and verify them with `isZodSchema()` in one place before handing them to `<Composition>`/`<Still>`.
- Keep a single Zod dependency/version in the project to avoid mixing schema instances from different builds.
When it happens
Trigger: A `<Composition schema={...}>` (or `<Still>`) whose value is truthy but has no `safeParse` method: e.g. `schema={{title: z.string()}}` (plain object of fields), `schema={z.object}` (the factory, not its result), or `schema={zodNamespace}`. The throw happens when Studio opens/renders the schema editor for that composition.
Common situations: Confusing the shape object with a wrapped schema; passing JSON Schema instead of Zod; importing two different schema libraries or a custom `z` namespace whose values are not Zod types; refactors that accidentally pass `defaultProps`-style objects as `schema`.
Related errors
- <Composition> was mounted inside the `component` that was pa
- <Composition> mounted inside another composition. See https:
- TimelineFontWeightField rendered for non-font-weight field
- inputRange must contain only numbers
- outputStyles must contain only objects
AI-assisted analysis of remotion-dev/remotion@10db9de073 (2026-08-22).
Data as JSON: /api/errors/40eb8da6914c62b6.
Report an issue: GitHub.