{"record":{"id":"d19b246d8296f749","repo":"remotion-dev/remotion","slug":"could-not-locate-the-visual-control-value","errorCode":null,"errorMessage":"Could not locate the visual control value","messagePattern":"Could not locate the visual control value","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio-codemods/src/apply-visual-control.ts","lineNumber":89,"sourceCode":"\t\t\tconst change = matchingChanges.at(-1);\n\t\t\tif (!change) {\n\t\t\t\treturn this.traverse(path);\n\t\t\t}\n\n\t\t\tconst serialized = change.newValueIsUndefined\n\t\t\t\t? 'undefined'\n\t\t\t\t: stringifyDefaultProps({\n\t\t\t\t\t\tprops: JSON.parse(change.newValueSerialized),\n\t\t\t\t\t\tenumPaths: change.enumPaths,\n\t\t\t\t\t});\n\t\t\tif (serialized === undefined) {\n\t\t\t\tthrow new Error('Could not serialize the visual control value');\n\t\t\t}\n\n\t\t\tconst secondArgument = node.arguments[1];\n\t\t\tif (secondArgument) {\n\t\t\t\tif (!secondArgument.loc) {\n\t\t\t\t\tthrow new Error('Could not locate the visual control value');\n\t\t\t\t}\n\n\t\t\t\tconst start = recastLocToOffset(input, secondArgument.loc.start);\n\t\t\t\tconst end = recastLocToOffset(input, secondArgument.loc.end);\n\t\t\t\tconst lineStart = input.lastIndexOf('\\n', start - 1) + 1;\n\t\t\t\tedits.push({\n\t\t\t\t\tstart,\n\t\t\t\t\tend,\n\t\t\t\t\treplacement: formatSerializedValue({\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\tlinePrefix: input.slice(lineStart, start),\n\t\t\t\t\t\tpreviousValue: input.slice(start, end).trim(),\n\t\t\t\t\t\tserialized,\n\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tif (!firstArgument.loc) {\n\t\t\t\t\tthrow new Error('Could not locate the visual control identifier');","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio-codemods/src/apply-visual-control.ts#L71-L107","documentation":"When a visualControl() call already has a second argument, the codemod must know its exact source offsets to replace it. Recast normally preserves source locations, but if the argument node lacks a .loc, no source range can be computed, so the codemod throws this error.","triggerScenarios":"Visiting a visualControl() call whose node.arguments[1] exists but has loc === undefined — typically because the AST was transformed/generated by recast (e.g. prior codemods inserted the node) rather than parsed directly from source.","commonSituations":"Chaining codemods on the same file where an earlier step programmatically built the visualControl() call; parsing/printing round-trips that drop location info.","solutions":["Re-parse the original source and run the codemod on a freshly parsed AST","Reformat the file (prettier) and retry so the argument exists as real source text","Replace the value manually if locations cannot be recovered"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"const hasLocatedArgs = (node: any) => node.arguments[1] && node.arguments[1].loc !== undefined;","typeGuard":"const hasLoc = (n: {loc?: unknown}): n is {loc: NonNullable<unknown>} => n.loc != null;","tryCatchPattern":"try {\n  applyVisualControl({input, transformation});\n} catch (e) {\n  if ((e as Error).message.includes('Could not locate the visual control value')) {\n    input = format(input); // reparse + retry\n    applyVisualControl({input, transformation});\n  }\n}","preventionTips":["Run codemods on freshly parsed source, not on recast-printed/re-parsed intermediate ASTs","Avoid chaining transformations that synthesize visualControl call nodes","Persist to disk and reformat between chained codemod steps"],"tags":["codemod","ast","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"}