{"record":{"id":"ba2e3529f4e59e2c","repo":"remotion-dev/remotion","slug":"could-not-split-video-from-audio","errorCode":null,"errorMessage":"Could not split video from audio","messagePattern":"Could not split video from audio","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-studio/src/browser-studio-operations.ts","lineNumber":1921,"sourceCode":"\t\t\t\t\tnodePath,\n\t\t\t\t\tformatFile: formatCodemodFile,\n\t\t\t\t});\n\t\t\t\tconst nodePathMutation = controller.applyMutation({\n\t\t\t\t\ttimelineSelection: null,\n\t\t\t\t\tfileName: absolutePath,\n\t\t\t\t\tmutate: () => ({\n\t\t\t\t\t\t...project,\n\t\t\t\t\t\tfiles: {...project.files, [absolutePath]: result.output},\n\t\t\t\t\t}),\n\t\t\t\t\tnodePathMutationFiles: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tabsolutePath,\n\t\t\t\t\t\t\tremappings: result.nodePathRemappings,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t\tif (nodePathMutation === null) {\n\t\t\t\t\tthrow new Error('Could not split video from audio');\n\t\t\t\t}\n\n\t\t\t\treturn {success: true, nodePathMutation};\n\t\t\t} catch (error) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\treason: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tstack: error instanceof Error && error.stack ? error.stack : '',\n\t\t\t\t};\n\t\t\t}\n\t\t};\n\n\tconst insertJsxElement: BrowserStudioOperations['insertJsxElement'] = async (\n\t\trequest,\n\t) => {\n\t\ttry {\n\t\t\tconst requiredPackage = getRequiredPackageForInsertableElement(\n\t\t\t\trequest.element,","sourceCodeStart":1903,"sourceCodeEnd":1939,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/browser-studio/src/browser-studio-operations.ts#L1903-L1939","documentation":"Returned as `{success: false, reason}` by splitVideoFromAudio in @remotion/browser-studio. The split codemod produced new file contents, but `controller.applyMutation(...)` with the node-path remappings returned null — the controller could not apply the mutation to its tracked state. The overwhelmingly common cause is a stale `nodePath` for the <Video> node being split.","triggerScenarios":"Calling `splitVideoFromAudio({fileName, nodePath})` where nodePath pointed at a video node that has since moved or been removed; splitting while another mutation is in flight; nodePath computed from an older version of the file.","commonSituations":"Context-menu 'split video/audio' in a custom editor using cached node paths; undo/redo between selection and the split action; concurrent edits from a second client.","solutions":["Re-resolve the video node's path from the current project state and retry","Confirm the target node is still a video element at that path","Serialize mutations so paths cannot change between read and write","Report a bug with file contents if it fails on freshly resolved paths"],"exampleFix":"// before\nawait operations.splitVideoFromAudio({fileName, nodePath: cachedPath});\n\n// after\nconst nodePath = await resolveCurrentVideoNodePath(fileName);\nconst res = await operations.splitVideoFromAudio({fileName, nodePath});\nif (!res.success) {\n  await refreshTimeline(); // paths went stale, let user retry\n}","handlingStrategy":"validation","validationCode":"const nodePath = await resolveCurrentVideoNodePath(fileName);\nif (nodePath === null) throw new Error('No video node found to split');\nconst res = await operations.splitVideoFromAudio({fileName, nodePath});\nif (!res.success) await refreshTimeline();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Resolve the video node path at action time, not at selection time","Disable split actions when the selection's node path is older than the last applied mutation"],"tags":["video","audio","node-path","mutation","browser-studio"],"backgroundTag":"invalid-node-path","analyzedSha":"b2f4e34732f3c6c222ea029413e22dc402218cd7","analyzedAt":"2026-08-22T21:45:17.748Z","contentChangedAt":"2026-08-22T21:45:17.748Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}