remotion-dev/remotion · error · Error
A Remotion upgrade is already in progress.
Error message
A Remotion upgrade is already in progress.
What it means
The upgrade endpoint serializes upgrades with a module-level `upgrading` flag. If an upgrade is already running in the Studio server process, a second concurrent request is rejected with this error until the first finishes.
Source
Thrown at packages/studio-server/src/preview-server/routes/upgrade-remotion.ts:18
import {spawn} from 'node:child_process';
import path from 'node:path';
import {RenderInternals} from '@remotion/renderer';
import type {ApiRoutes} from '@remotion/studio-shared';
import type {ApiHandler} from '../api-types';
let upgrading = false;
export const handleUpgradeRemotion: ApiHandler<
ApiRoutes['/api/upgrade-remotion']['Request'],
ApiRoutes['/api/upgrade-remotion']['Response']
> = async ({remotionRoot, logLevel, input: {version}}) => {
if (typeof version !== 'string' || !/^\d+\.\d+\.\d+$/.test(version)) {
throw new Error('Invalid Remotion version.');
}
if (upgrading) {
throw new Error('A Remotion upgrade is already in progress.');
}
upgrading = true;
try {
const cliPackage = require.resolve('@remotion/cli/package.json', {
paths: [remotionRoot],
});
const cli = path.join(path.dirname(cliPackage), 'remotion-cli.js');
await new Promise<void>((resolve, reject) => {
const child = spawn(
process.execPath,
[cli, 'upgrade', `--version=${version}`],
{
cwd: remotionRoot,
stdio: ['ignore', 'pipe', 'pipe'],
env: {...process.env, CI: '1'},
},
);View on GitHub (pinned to b2f4e34732)
Solutions
- Wait for the in-progress upgrade to complete, then retry.
- Check the Studio terminal/logs for the running upgrade's progress or failure before retrying.
- Restart the Studio dev server if a crashed upgrade left the flag stuck (the flag resets only on process restart in that case).
- Trigger upgrades from a single place — avoid concurrent requests from multiple tabs or scripts.
Example fix
// before
Promise.all([upgradeRemotion('4.0.2'), upgradeRemotion('4.0.3')]);
// after
await upgradeRemotion('4.0.3'); Defensive patterns
Strategy: try-catch
Validate before calling
// client-side single-flight guard
let upgrading = false;
async function safeUpgrade(v: string) {
if (upgrading) return;
upgrading = true;
try { await upgradeRemotion(v); } finally { upgrading = false; }
} Try / catch
try {
await upgradeRemotion(version);
} catch (e) {
if (e.message.includes('already in progress')) {
await waitForUpgradeCompletion(); // poll logs, then retry once
} else throw e;
} Prevention
- Trigger upgrades from a single UI/tab only.
- Debounce/dedupe upgrade requests client-side.
- Monitor the Studio terminal for the running upgrade before retrying.
- If the flag seems stuck, restart the Studio server.
When it happens
Trigger: Issuing a second /api/upgrade-remotion request while a previous upgrade (npm install of @remotion/cli etc.) is still executing in the same Studio server process.
Common situations: Double-clicking an upgrade button, retry loops firing while the first upgrade is in flight, multiple browser tabs triggering upgrades simultaneously.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Job is not running
- <Clipper> has been removed as of Remotion v4.0.228. The nati
- Invalid ElevenLabs transcript. The transcript must be genera
- Parameter 'durationInMilliseconds' must be a number but got
- Parameter 'durationInMilliseconds' must not be NaN but it is
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09).
Data as JSON: /api/errors/20ffd030c9216e5e.
Report an issue: GitHub.