{"record":{"id":"51a3cda30358b455","repo":"remotion-dev/remotion","slug":"cannot-duplicate-a-jsx-element-without-a-source-location","errorCode":null,"errorMessage":"Cannot duplicate a JSX element without a source location","messagePattern":"Cannot duplicate a JSX element without a source location","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio-codemods/src/duplicate-jsx-node.ts","lineNumber":182,"sourceCode":"\tconst clone = cloneJsxElement(jsxNode);\n\tuniquifyNamePropOnClone(clone);\n\n\tif (insertDuplicateForParent(parentPath.node, jsxNode, clone)) {\n\t\treturn;\n\t}\n\n\tjsxPath.replace(makeFragment(jsxNode, clone));\n};\n\nconst getDuplicatedJsxSource = ({\n\telement,\n\tinput,\n}: {\n\telement: JSXElement;\n\tinput: string;\n}) => {\n\tif (!element.loc) {\n\t\tthrow new Error('Cannot duplicate a JSX element without a source location');\n\t}\n\n\tconst start = recastLocToOffset(input, element.loc.start);\n\tconst end = recastLocToOffset(input, element.loc.end);\n\tlet source = input.slice(start, end);\n\tconst nameAttribute = element.openingElement.attributes.find(\n\t\t(attribute) =>\n\t\t\tattribute.type === 'JSXAttribute' &&\n\t\t\tattribute.name.type === 'JSXIdentifier' &&\n\t\t\tattribute.name.name === 'name' &&\n\t\t\t(attribute.value?.type === 'StringLiteral' ||\n\t\t\t\t(attribute.value?.type === 'JSXExpressionContainer' &&\n\t\t\t\t\tattribute.value.expression.type === 'StringLiteral')),\n\t);\n\n\tif (nameAttribute?.type === 'JSXAttribute') {\n\t\tconst value =\n\t\t\tnameAttribute.value?.type === 'JSXExpressionContainer'","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio-codemods/src/duplicate-jsx-node.ts#L164-L200","documentation":"getDuplicatedJsxSource slices the original source text of the element to build the duplicated copy. If the JSXElement has no .loc, there is no source range to slice — the node isn't backed by source text — so duplication of source is impossible and it throws.","triggerScenarios":"duplicateJsxNodes (Studio duplicate-node action) resolves a node path to a JSX element whose loc is undefined — typically an element created by AST transformation rather than present in the original file.","commonSituations":"Duplicating a JSX node in a file that was previously generated/rewritten by codemods; stale Studio node paths pointing at synthesized nodes.","solutions":["Reload the file in Studio so the AST is re-parsed from disk with fresh locations","Ensure the target element exists as literal source text (not codegen) and retry the duplicate action","Duplicate the JSX block manually"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"const nodeHasSource = (ast: any) => JSON.stringify(ast).includes('\"loc\":null') === false;","typeGuard":"const hasLoc = (n: {loc?: unknown}): n is {loc: NonNullable<unknown>} => n.loc != null;","tryCatchPattern":"try {\n  await duplicateJsxNodes({input, nodePaths});\n} catch (e) {\n  if ((e as Error).message.includes('without a source location')) {\n    // reload/reparse the file so nodes regain locations, then retry\n  }\n}","preventionTips":["Reload the Studio composition/file before duplicating after bulk edits","Only duplicate nodes that exist in the saved source file","Avoid duplicating nodes created by prior in-memory AST transformations"],"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"}