{"record":{"id":"a951a0951b5aaf4d","repo":"remotion-dev/remotion","slug":"could-not-locate-the-composition-to-duplicate","errorCode":null,"errorMessage":"Could not locate the composition to duplicate","messagePattern":"Could not locate the composition to duplicate","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio-codemods/src/duplicate-composition.ts","lineNumber":239,"sourceCode":"\tconst changesMade: {description: string}[] = [];\n\tconst edits: SourceEdit[] = [];\n\tconst snapshots = captureImportSnapshots(ast);\n\n\trecast.types.visit(ast, {\n\t\tvisitJSXElement(astPath) {\n\t\t\tconst original = astPath.node as unknown as JSXElement;\n\t\t\tif (getCompositionId(original) !== codemod.idToDuplicate) {\n\t\t\t\tthis.traverse(astPath);\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst duplicate = changeComposition({\n\t\t\t\tjsxElement: original,\n\t\t\t\tcodemod,\n\t\t\t\tchangesMade,\n\t\t\t});\n\t\t\tif (!original.loc) {\n\t\t\t\tthrow new Error('Could not locate the composition to duplicate');\n\t\t\t}\n\n\t\t\tconst insertion = printInsertedJsx({\n\t\t\t\telement: duplicate as never,\n\t\t\t\tinput,\n\t\t\t\tprettierConfigOverride: null,\n\t\t\t});\n\t\t\tconst parent = astPath.parentPath?.node;\n\t\t\tif (\n\t\t\t\tparent &&\n\t\t\t\t(parent.type === 'JSXElement' || parent.type === 'JSXFragment')\n\t\t\t) {\n\t\t\t\tconst end = recastLocToOffset(input, original.loc.end);\n\t\t\t\tconst start = recastLocToOffset(input, original.loc.start);\n\t\t\t\tconst lineStart = input.lastIndexOf('\\n', start - 1) + 1;\n\t\t\t\tconst indent =\n\t\t\t\t\tinput.slice(lineStart, start).match(/^[\\t ]*/)?.[0] ?? '';\n\t\t\t\tconst endOfLine = input.includes('\\r\\n') ? '\\r\\n' : '\\n';","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio-codemods/src/duplicate-composition.ts#L221-L257","documentation":"duplicateCompositionInSource builds a duplicate of the matched <Composition> as an AST node, then needs the original element's source location to compute where to insert the copy. If original.loc is undefined (the matched node is not backed by real source text), the insertion offset cannot be derived and it throws.","triggerScenarios":"Visiting the JSX element whose id matches codemod.idToDuplicate where the element node has no loc — e.g. the composition was generated into the AST by a prior transformation rather than parsed from source.","commonSituations":"Duplicating a composition in a file that was previously machine-modified; chained codemods where an earlier step synthesized the Composition element.","solutions":["Re-run duplicateCompositionInSource on the freshly parsed original file","Save and reformat the file so the <Composition> exists as literal source, then retry","Copy the <Composition> block manually in the editor"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"const hasLiteralComposition = new RegExp(`<Composition[^>]*id=\"${id}\"`).test(input);\nif (!hasLiteralComposition) throw new Error('Composition must exist as literal source to duplicate');","typeGuard":"const hasLoc = (n: {loc?: unknown}): n is {loc: NonNullable<unknown>} => n.loc != null;","tryCatchPattern":"try {\n  duplicateCompositionInSource({input, codemod});\n} catch (e) {\n  if ((e as Error).message.includes('Could not locate the composition to duplicate')) {\n    // reparse original file / save + format to disk, then retry\n  }\n}","preventionTips":["Run duplication on freshly parsed original source","Avoid chained codemods that synthesize Composition nodes without locations","Keep compositions as literal JSX in Root"],"tags":["codemod","jsx","source-locations"],"backgroundTag":"internal-invariant-violation","analyzedSha":"46a3a6bf13ca367376ff18bbb06dae2e87e0d068","analyzedAt":"2026-09-18T00:12:20.256Z","contentChangedAt":"2026-09-18T00:12:20.256Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}