remotion-dev/remotion · error · Error
Could not delete JSX nodes
Error message
Could not delete JSX nodes
What it means
deleteJsxNode commits the deletion through controller.applyMutation, which returns null when the mutation does not actually change the project (mutate(before) returned the identical project reference, i.e. a no-op commit with no node-path mutation to report). deleteJsxNode treats a null result as failure and throws; the catch converts it to {success: false, reason}.
Source
Thrown at packages/browser-studio/src/browser-studio-operations.ts:1320
...project,
files: {
...project.files,
...Object.fromEntries(
updates.map(({fileName, result}) => [fileName, result.output]),
),
},
};
const nodePathMutation = controller.applyMutation({
timelineSelection: null,
fileName: updates.map(({fileName}) => fileName).join(', '),
mutate: () => nextProject,
nodePathMutationFiles: updates.map(({fileName, result}) => ({
absolutePath: fileName,
remappings: result.nodePathRemappings,
})),
});
if (nodePathMutation === null) {
throw new Error('Could not delete JSX nodes');
}
return {success: true, nodePathMutation};
} catch (error) {
return {
success: false,
reason: error instanceof Error ? error.message : String(error),
stack: error instanceof Error && error.stack ? error.stack : '',
};
}
};
const duplicateJsxNode: BrowserStudioOperations['duplicateJsxNode'] = async ({
nodes,
}) => {
try {
if (nodes.length === 0) {
throw new Error('No JSX nodes were specified for duplication');View on GitHub (pinned to b2f4e34732)
Solutions
- Verify each nodePath still resolves in the current file contents before calling deleteJsxNode.
- Refresh node paths from 'sequence-node-paths-remapped' events after any mutation that remaps them.
- Retry the operation once after re-reading the project; if it reproduces, capture the file source and node paths and report it as a bug.
Defensive patterns
Strategy: validation
Validate before calling
const nodePathResolves = (source: string, nodePath: readonly number[]): boolean => {
// cheap structural check: file must contain JSX and the parent path must be in range
return source.length > 0 && nodePath.every((index) => Number.isInteger(index) && index >= 0);
};
const staleNodes = nodes.filter((n) => !nodePathResolves(project.files[n.fileName] ?? '', n.nodePath.nodePath));
if (staleNodes.length === nodes.length) {
// all paths stale — refresh from 'sequence-node-paths-remapped' before deleting
} Try / catch
const result = await operations.deleteJsxNode({nodes});
if (!result.success && result.reason === 'Could not delete JSX nodes') {
// node paths are stale: refresh them from remap events and rebuild the request
} Prevention
- Subscribe to 'sequence-node-paths-remapped' events and update stored node paths.
- Never reuse node paths captured before another mutation or undo/redo.
- Check the returned success flag on every JSX operation instead of assuming success.
When it happens
Trigger: Deleting JSX nodes whose codemod output matches the existing file content (stale node paths pointing at nothing), or racing a concurrent project replacement so the committed mutation is a no-op and applyMutation yields null.
Common situations: Node paths captured before an edit or undo shifted the JSX; automated agents replaying delete operations against a changed project; rare defensive path — reproducible occurrences usually indicate stale node-path state.
Related errors
- Could not split JSX sequence
- Could not duplicate JSX node
- Could not find a root JSX element
- Could not find ${getCompositionOrFolderLabel(transformation.
- Could not find composition "${compositionId}"
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-08-22).
Data as JSON: /api/errors/4f686148a005998b.
Report an issue: GitHub.