remotion-dev/remotion · error

Invalid Element source

Error message

Invalid Element source

What it means

getElementInstallPlanForProject (behind prepareElementInstall) parses the Remotion Element payload before insertion: it extracts the exported component name from element.sourceCode (StudioProtocolInternals.getElementComponentNameFromSourceCode) and derives a file name from element.slug (makeElementFileNameFromSlug). If either returns null, the payload cannot be turned into a project file and 'Invalid Element source' is thrown.

Source

Thrown at packages/browser-studio/src/browser-studio-operations.ts:343

	const componentName =
		StudioProtocolInternals.getElementComponentNameFromSourceCode(
			element.sourceCode,
		);
	const elementFileName = StudioProtocolInternals.makeElementFileNameFromSlug(
		installationName ?? element.slug,
	);
	if (
		elementFileName === null ||
		(typeof installationName === 'string' &&
			elementFileName !== `${installationName}.element.tsx`)
	) {
		throw new Error(
			'Use a lowercase installation name with letters, numbers and hyphens, without a file extension.',
		);
	}

	if (componentName === null) {
		throw new Error('Invalid Element source');
	}

	const target =
		destination.type === 'current-composition'
			? await resolveCompositionComponentWithFile({
					compositionFile: destination.compositionFile,
					compositionId: destination.compositionId,
					environment: makeInMemoryInsertJsxElementCodemodEnvironment({
						project,
						svgMarkupToJsx,
					}),
				})
			: null;
	if (target !== null && !target.canAddSequence) {
		throw new Error('Cannot insert Element into this composition component');
	}

	const rootFile =

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Regenerate the payload with createElementPayload from the current @remotion/studio-protocol instead of constructing it by hand.
  2. Ensure element.sourceCode exports a named React component (e.g. export const MyElement: React.FC = ...).
  3. Use a non-empty, filename-safe kebab-case slug.
  4. Align all @remotion/* package versions so payload formats match.
Defensive patterns

Strategy: validation

Validate before calling

const isValidElementPayload = (payload: {
  slug: string;
  sourceCode: string;
}): boolean =>
  payload.slug.length > 0 &&
  /export\s+(const|function)\s+[A-Z][A-Za-z0-9_]*/.test(payload.sourceCode);

Type guard

const isInstallableElementPayload = (
  payload: StudioElementPayload,
): payload is StudioElementPayload & {slug: string; sourceCode: string} =>
  typeof payload.slug === 'string' &&
  payload.slug.length > 0 &&
  typeof payload.sourceCode === 'string' &&
  /export\s+(const|function)\s+[A-Z][A-Za-z0-9_]*/.test(payload.sourceCode);

Try / catch

try {
  const plan = await operations.element.prepareElementInstall(request);
} catch (error) {
  if (error instanceof Error && error.message === 'Invalid Element source') {
    // regenerate the payload with createElementPayload from the current studio-protocol
  }
}

Prevention

When it happens

Trigger: prepareElementInstall with a StudioElementPayload whose sourceCode contains no recognizable exported component, or whose slug is empty/malformed so no valid element file name can be derived from it.

Common situations: Hand-built or serialized element payloads from an older @remotion/studio-protocol version; truncated or rewritten sourceCode that lost its export; slugs made only of characters invalid for file names; version skew between studio-protocol and browser-studio packages.

Related errors


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