remotion-dev/remotion · error

Could not locate the composition opening element

Error message

Could not locate the composition opening element

What it means

When metadata attributes (fps/durationInFrames/width/height) are missing from the composition, the codemod inserts them anchored at the opening element. If the openingElement or its name node lacks loc, the insertion offset cannot be computed and it throws.

Solutions

  1. Re-parse the original file and re-run the codemod
  2. Persist and reformat the file so the <Composition> tag is literal source, then retry
  3. Add the missing attributes manually

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

if (!/<Composition[\s\S]*?id=/.test(input)) throw new Error('Composition opening element must be literal source');

Type guard

const openingHasLoc = (el: any) => el.openingElement?.loc != null && el.openingElement.name?.loc != null;

Try / catch

try {
  editCompositionInSource({input, codeMod});
} catch (e) {
  if ((e as Error).message.includes('Could not locate the composition opening element')) {
    // reparse from original source or add the missing attributes manually
  }
}

Prevention

When it happens

Trigger: update-composition-metadata codemod on a matching <Composition> where required metadata attributes are absent and element.openingElement.loc or openingElement.name.loc is undefined (synthesized opening element without source locations).

Common situations: Composition JSX generated by earlier codemods or codegen that didn't preserve recast location data.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at packages/studio-codemods/src/composition-source-edits.ts:221

							});
						} else {
							throw new Error(
								`Could not locate the "${update.name}" attribute`,
							);
						}

						changesMade.push({
							description: `Replaced ${update.description}`,
						});
					}

					const missingMetadata = metadata.filter(
						(item) => item.value !== null && !existingMetadata.has(item.name),
					);
					if (missingMetadata.length > 0) {
						const {openingElement} = element;
						if (!openingElement.loc || !openingElement.name.loc) {
							throw new Error(
								'Could not locate the composition opening element',
							);
						}

						const openingEnd = recastLocToOffset(input, openingElement.loc.end);
						const closingStart =
							openingEnd - (openingElement.selfClosing ? 2 : 1);
						const lastAttribute = openingElement.attributes.findLast(
							(candidate) => candidate.loc,
						);
						const anchor =
							lastAttribute?.loc?.end ?? openingElement.name.loc.end;
						const anchorOffset = recastLocToOffset(input, anchor);
						const rendered = missingMetadata.map(
							(item) => `${item.name}={${item.value}}`,
						);

						if (input.slice(anchorOffset, closingStart).includes('\n')) {

View on GitHub (pinned to 46a3a6bf13)