remotion-dev/remotion · error
Element source changed during installation
Error message
Element source changed during installation
What it means
Surfaced by insertElement in @remotion/browser-studio (as `{success: false, type: 'error', reason}`) when the caller passed a non-null `expectedFileState` that no longer matches the plan's actual file state, AND the plan has no `existingSource` (so the structured 'file-conflict' response is impossible). expectedFileState is an optimistic-concurrency token from prepareElementInstall: it proves the element file on disk is still in the state the client last saw. A mismatch means the element file changed by other means between prepare and install.
Source
Thrown at packages/browser-studio/src/browser-studio-operations.ts:2072
request.expectedFileState !== null &&
!expectedFileStateMatches({
actual: plan.expectedFileState,
expected: request.expectedFileState,
})
) {
if (plan.existingSource !== null) {
return {
success: false,
type: 'file-conflict',
conflict: {
existingSource: plan.existingSource,
filePath: plan.filePath,
incomingSource: request.element.sourceCode,
},
};
}
throw new Error('Element source changed during installation');
}
if (!request.overwriteExisting && plan.existingSource !== null) {
return {
success: false,
type: 'file-conflict',
conflict: {
existingSource: plan.existingSource,
filePath: plan.filePath,
incomingSource: request.element.sourceCode,
},
};
}
const installedDependencies = await resolveElementDependencies(
request.element.dependencies,
);
const installationMode = request.element.installationMode ?? 'wrapped';View on GitHub (pinned to b2f4e34732)
Solutions
- Re-run prepareElementInstall to get a fresh expectedFileState and repeat the install with it
- Pass `expectedFileState: null` to skip the staleness check when overwrite is acceptable
- Handle the 'file-conflict' response type (existingSource present) by asking the user to overwrite or keep both
- Avoid mutating element files while an install is in flight
Example fix
// before
await operations.insertElement({
element,
compositionFile,
compositionId,
expectedFileState: stalePlan.expectedFileState, // from an old prepare call
overwriteExisting: false,
});
// after
const plan = await operations.prepareElementInstall({element, compositionFile, compositionId});
if (!plan.success) throw new Error(plan.reason);
const res = await operations.insertElement({
element,
compositionFile,
compositionId,
expectedFileState: plan.plan.expectedFileState, // fresh token
overwriteExisting: false,
});
if (!res.success && res.type === 'file-conflict') {
// ask user, then retry with overwriteExisting: true
} Defensive patterns
Strategy: validation
Validate before calling
const plan = await operations.prepareElementInstall({element, compositionFile, compositionId});
if (!plan.success) throw new Error(plan.reason);
// use the fresh token; pass null to skip the check when overwriting is fine
const res = await operations.insertElement({element, compositionFile, compositionId, expectedFileState: plan.plan.expectedFileState, overwriteExisting: false});
if (!res.success && res.type === 'file-conflict') { /* ask user, retry with overwriteExisting: true */ } Prevention
- Always pair insertElement with a just-fetched prepareElementInstall token; never reuse tokens across user actions
- Handle both failure shapes: type 'file-conflict' (structured) and type 'error' with this reason
- Lock element files against manual edits while an install is in flight
When it happens
Trigger: Calling `insertElement({element, compositionFile, compositionId, expectedFileState, ...})` where expectedFileState came from an earlier prepareElementInstall and the target file has since been edited, restored, or re-scaffolded; passing an expectedFileState belonging to a different element file path.
Common situations: User edits the element file in an editor between previewing and installing the Element; two installs of related Elements race; an undo restored an older version of the element file mid-install.
Related errors
- Could not insert Element
- Element source changed during installation
- Could not insert JSX element
- Cannot insert Element into this composition component
- Element source file conflicts with the composition file
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09).
Data as JSON: /api/errors/9151a04e7855490f.
Report an issue: GitHub.