remotion-dev/remotion · error · Error

Component-owned Element initial style must be an object

Error message

Component-owned Element initial style must be an object

What it means

For a component-owned Element, initialProps.style (if provided) must be a non-null, non-array object that can be merged into the Element's style. The route throws when style is null, not an object, or an array.

Solutions

  1. Pass style as a plain object, e.g. {width: 100}
  2. Omit the style key entirely if no initial style is needed
  3. Parse stringified CSS-in-JSON into a real object before sending the request

Example fix

// before
initialProps: { style: '{"width": 100}' }
// after
initialProps: { style: { width: 100 } }
Defensive patterns

Strategy: type-guard

Validate before calling

if (el.initialProps?.style != null && (typeof el.initialProps.style !== 'object' || Array.isArray(el.initialProps.style))) {
  throw new TypeError('style must be a plain object');
}

Type guard

const isStyleObject = (s: unknown): s is Record<string, string | number> =>
  typeof s === 'object' && s !== null && !Array.isArray(s);

Try / catch

try {
  await insertElement(payload);
} catch (e) {
  if (/initial style must be an object/.test(e.message)) {
    payload.element.initialProps.style = JSON.parse(String(payload.element.initialProps.style));
  }
}

Prevention

When it happens

Trigger: POSTing to insert-element where componentOwnsSequence is true and element.initialProps.style is null, a primitive (e.g. a string), or an array.

Common situations: Generated requests serializing style as a JSON string ('{"width": 100}') or as an array of style objects instead of a single merged object.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of remotion-dev/remotion@46a3a6bf13 (2026-09-18). Data as JSON: /api/errors/03894a9ed1b8088c. Report an issue: GitHub.

Appendix: source

Thrown at packages/studio-server/src/preview-server/routes/insert-element.ts:112

				componentOwnsSequence &&
				element.initialProps !== null &&
				['from', 'durationInFrames', 'name'].some((prop) =>
					Object.hasOwn(element.initialProps ?? {}, prop),
				)
			) {
				throw new Error(
					'Component-owned Element initial props must not override from, durationInFrames, or name',
				);
			}

			if (
				componentOwnsSequence &&
				element.initialProps?.style !== undefined &&
				(element.initialProps.style === null ||
					typeof element.initialProps.style !== 'object' ||
					Array.isArray(element.initialProps.style))
			) {
				throw new Error(
					'Component-owned Element initial style must be an object',
				);
			}

			RenderInternals.Log.trace(
				{indent: false, logLevel},
				`[insert-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.slug}"`,
			);

			let compositionCreation: {
				componentFilePath: string;
				componentFileContents: string;
				registrationFilePath: string;
				registrationFileOldContents: string;
				registrationFileNewContents: string;
			} | null = null;
			let sourceFileOverrides: ReadonlyMap<string, string> | null = null;

View on GitHub (pinned to 46a3a6bf13)