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

  1. Wait for the in-progress upgrade to complete, then retry.
  2. Check the Studio terminal/logs for the running upgrade's progress or failure before retrying.
  3. Restart the Studio dev server if a crashed upgrade left the flag stuck (the flag resets only on process restart in that case).
  4. 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

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


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09). Data as JSON: /api/errors/20ffd030c9216e5e. Report an issue: GitHub.