{"record":{"id":"71dff61864aeef1b","repo":"remotion-dev/remotion","slug":"cannot-split-a-jsx-sequence-without-a-source-locat","errorCode":null,"errorMessage":"Cannot split a JSX sequence without a source location","messagePattern":"Cannot split a JSX sequence without a source location","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio-codemods/src/split-jsx-sequence.ts","lineNumber":362,"sourceCode":"\tconst endOfLine = source.includes('\\r\\n') ? '\\r\\n' : '\\n';\n\treturn source.split(/\\r?\\n/).join(`${endOfLine}${indent}`);\n};\n\nconst getSplitSourceEdit = ({\n\tinput,\n\tleft,\n\tprettierConfigOverride,\n\tright,\n\twrapInFragment,\n}: {\n\tinput: string;\n\tleft: JSXElement;\n\tprettierConfigOverride: Record<string, unknown> | null;\n\tright: JSXElement;\n\twrapInFragment: boolean;\n}) => {\n\tif (!left.loc) {\n\t\tthrow new Error('Cannot split a JSX sequence without a source location');\n\t}\n\n\tconst start = recastLocToOffset(input, left.loc.start);\n\tconst end = recastLocToOffset(input, left.loc.end);\n\tconst lineStart = input.lastIndexOf('\\n', start - 1) + 1;\n\tconst beforeElement = input.slice(lineStart, start);\n\tconst lineIndent = beforeElement.match(/^\\s*/)?.[0] ?? '';\n\tconst isOnlyElementOnLine = beforeElement.trim() === '';\n\tconst endOfLine = input.includes('\\r\\n') ? '\\r\\n' : '\\n';\n\tconst formattingConfig = prettierConfigOverride ?? null;\n\tconst print = (element: JSXElement | JSXFragment) =>\n\t\tindentContinuationLines({\n\t\t\tindent: lineIndent,\n\t\t\tsource: printInsertedJsx({\n\t\t\t\telement: element as unknown as\n\t\t\t\t\t| AstNamedTypes.JSXElement\n\t\t\t\t\t| AstNamedTypes.JSXFragment,\n\t\t\t\tinput,","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/studio-codemods/src/split-jsx-sequence.ts#L344-L380","documentation":"getSplitSourceEdit computes a source text edit to split a JSX sequence by slicing the original source around the 'left' JSX element. Recast attaches source locations only to elements that were parsed from source (not synthesized nodes). If left.loc is missing, the element's position in the original file is unknown and the split cannot produce a text edit, so this error is thrown.","triggerScenarios":"Calling splitJsxSequence/sourceEdit where the left JSX element has no .loc — e.g. the element was programmatically synthesized by a previous codemod/recast transformation and printed without source positions, rather than originating from the parsed file.","commonSituations":"Chained codemods where a generated element is split in a second pass; running a split on AST nodes produced by replaceWith() instead of freshly parsed source.","solutions":["Re-parse the composition file after any generation step so the element has fresh source locations before splitting","Only split elements that came directly from the parsed file","Skip the split for elements lacking .loc and handle them via full-file rewrite instead"],"exampleFix":"// before\nconst ast = transform(generateElement()); // synthesized, no .loc\nsplit(ast);\n// after\nconst ast = parse(originalSource); // re-read from disk after prior writes\nsplit(ast);","handlingStrategy":"type-guard","validationCode":"if (!left.loc) {\n  // re-parse from source so recast attaches locations, then retry\n  ast = parse(originalSource);\n}","typeGuard":"const hasLoc = (el: JSXElement): el is JSXElement & {loc: NonNullable<JSXElement['loc']>} => el.loc !== null && el.loc !== undefined;","tryCatchPattern":"try {\n  edit = getSplitSourceEdit({left, ...});\n} catch (e) {\n  if (String(e).includes('without a source location')) {\n    // re-parse file and re-resolve the element before splitting\n  } else throw e;\n}","preventionTips":["Only split elements that originate from the parsed source file, not synthesized nodes","Re-parse the composition after any codegen step before running further codemods","Check .loc on nodes before computing text edits"],"tags":["codemod","ast","jsx"],"backgroundTag":"missing-source-location","analyzedSha":"b2f4e34732f3c6c222ea029413e22dc402218cd7","analyzedAt":"2026-09-02T16:25:19.997Z","contentChangedAt":"2026-09-02T16:25:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}