remotion-dev/remotion · error · Error
Could not locate the JSX element to move
Error message
Could not locate the JSX element to move
What it means
getJsxElementSourceForInsertion returns the original source string of a JSX element so it can be re-inserted elsewhere. It throws when the JSXElement AST node has no source location (element.loc is null), which makes it impossible to recover the element's text or its indentation.
Solutions
- Only pass JSXElements obtained from the recast-parsed original source; do not pass nodes you constructed yourself.
- If you cloned a node, preserve loc (or re-derive it) before calling, e.g. by keeping the original node reference.
- Re-parse the current source with recast so all nodes have loc, then locate the element again.
- Fall back to serializing the node with recast.print if you control the caller and loc cannot be restored.
Example fix
// before: passing a synthesized element
const text = getJsxElementSourceForInsertion({element: newElement, input});
// after: use the element found in the parsed tree
const parsed = parse(input).program.body[0]...;
const text = getJsxElementSourceForInsertion({element: parsedElement, input}); Defensive patterns
Strategy: type-guard
Validate before calling
if (!element.loc) {
throw new Error('Element must come from a recast-parsed source tree');
} Type guard
const isLocatable = <T extends {loc: unknown}>(node: T): node is T & {loc: NonNullable<T['loc']>} => node.loc != null; Try / catch
try {
const src = getJsxElementSourceForInsertion({element, input});
} catch (err) {
// fall back to recast.print(element).code
} Prevention
- Always source JSXElement nodes from the recast parse of the file
- Do not clone or spread AST nodes; keep original references
- Re-parse after any in-memory mutation before computing source edits
- Assert node.loc exists at codemod entry points
When it happens
Trigger: Calling this helper with a JSXElement that was created or cloned programmatically during the codemod (no loc), or with an element from a second parse that was not passed through recast's location-recording parser.
Common situations: Chained codemods where a transform builds a new JSXElement and another helper is expected to move it; cloning a node with {...node} without loc; parsing with a parser option that strips loc data.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Cannot duplicate JSX element with no parent
- Cannot split a JSX sequence without a source location
- Cannot split JSX sequence with no parent
- Could not find a root JSX element
- Could not find a root JSX element
AI-assisted analysis of remotion-dev/remotion@46a3a6bf13 (2026-09-18).
Data as JSON: /api/errors/ec82335e39c9b148.
Report an issue: GitHub.
Appendix: source
Thrown at packages/studio-codemods/src/source-edits.ts:68
.replaceAll("'", ''')
.replaceAll('<', '<') +
quote
: recast.prettyPrint(recast.types.builders.stringLiteral(newValue), {
quote: quote === "'" ? 'single' : 'double',
}).code;
return {start, end, replacement};
};
export const getJsxElementSourceForInsertion = ({
element,
input,
}: {
element: JSXElement;
input: string;
}): string => {
if (!element.loc) {
throw new Error('Could not locate the JSX element to move');
}
const start = recastLocToOffset(input, element.loc.start);
const end = recastLocToOffset(input, element.loc.end);
const originalIndent = getLineIndent({input, offset: start});
return input
.slice(start, end)
.split(/\r?\n/)
.map((line, index) => {
if (index === 0) {
return line;
}
return line.startsWith(originalIndent)
? line.slice(originalIndent.length)
: line.trimStart();
})View on GitHub (pinned to 46a3a6bf13)