{"record":{"id":"7113655b823a2ad9","repo":"remotion-dev/remotion","slug":"could-not-locate-the-jsx-reorder-target-source-edits","errorCode":null,"errorMessage":"Could not locate the JSX reorder target","messagePattern":"Could not locate the JSX reorder target","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/studio-codemods/src/source-edits.ts","lineNumber":102,"sourceCode":"\t\t\t\t? line.slice(originalIndent.length)\n\t\t\t\t: line.trimStart();\n\t\t})\n\t\t.join(getEndOfLine(input));\n};\n\nexport const getAdjacentJsxInsertionSourceEdit = ({\n\tinput,\n\tinsertion,\n\tposition,\n\ttarget,\n}: {\n\tinput: string;\n\tinsertion: string;\n\tposition: 'after' | 'before';\n\ttarget: JSXElement;\n}): SourceEdit => {\n\tif (!target.loc) {\n\t\tthrow new Error('Could not locate the JSX reorder target');\n\t}\n\n\tconst targetStart = recastLocToOffset(input, target.loc.start);\n\tconst targetEnd = recastLocToOffset(input, target.loc.end);\n\tconst indent = getLineIndent({input, offset: targetStart});\n\tconst endOfLine = getEndOfLine(input);\n\n\tif (position === 'after') {\n\t\treturn {\n\t\t\tstart: targetEnd,\n\t\t\tend: targetEnd,\n\t\t\treplacement: `${endOfLine}${indentInsertedJsx({indent, insertion})}`,\n\t\t};\n\t}\n\n\tconst continuation = insertion\n\t\t.split(/\\r?\\n/)\n\t\t.map((line, index) => (index === 0 ? line : `${indent}${line}`))","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio-codemods/src/source-edits.ts#L84-L120","documentation":"getAdjacentJsxInsertionSourceEdit computes an insertion point just before or after a target JSX element to implement reordering. It throws when the target JSXElement has no source location, so the codemod cannot determine where to insert the sibling markup.","triggerScenarios":"Calling with a target JSXElement synthesized in-memory (no loc), or an element whose loc was dropped by cloning/mutation in a prior transform step.","commonSituations":"Reordering elements in Studio's timeline codemods when the target was produced by a previous edit; parsing source without recast loc recording; moving a newly-created component into an existing sibling list.","solutions":["Pick the reorder target from the original recast-parsed tree so it carries loc.","If the target was newly created, first insert it via an edit, re-parse, then reorder using the re-parsed node.","Restore loc on cloned nodes or keep the original node reference instead of spreading/cloning.","Guard with if (!target.loc) in your codemod and skip with a warning instead of throwing deep inside the library."],"exampleFix":"// before\napplySourceEdits({input, edits: [getAdjacentJsxInsertionSourceEdit({target: clonedEl, ...})]});\n// after\nconst realEl = findElementInParsedSource(input, elId);\napplySourceEdits({input, edits: [getAdjacentJsxInsertionSourceEdit({target: realEl, ...})]});","handlingStrategy":"type-guard","validationCode":"if (!target.loc) {\n  throw new Error('Reorder target must be a parsed node with location');\n}","typeGuard":"const hasLoc = (n: {loc: unknown}): n is {loc: NonNullable<typeof n.loc>} => n.loc != null;","tryCatchPattern":"try {\n  const edit = getAdjacentJsxInsertionSourceEdit({input, insertion, position, target});\n} catch (err) {\n  // re-parse input and retry with the corresponding parsed node\n}","preventionTips":["Select reorder targets from the freshly parsed tree","Re-parse between chained transforms so nodes regain loc","Avoid spreading JSXElement nodes when reordering; move references instead","Fail fast with your own loc assertion before calling library helpers"],"tags":["codemod","jsx","reorder","missing-loc"],"backgroundTag":"resource-not-found","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"}