remotion-dev/remotion · error · Error

installPackages() is not available in Read-Only Studio

Error message

installPackages() is not available in Read-Only Studio

What it means

Inside the Node-based Studio, installPackages() falls through to the local server API only when window.remotion_isReadOnlyStudio is false. Read-Only Studio is set when Studio is loaded from a static/index bundle without its server (renderEntry.tsx sets window.remotion_isReadOnlyStudio = true for bundleMode 'index') or when the Studio HTML is generated with the readOnlyStudio option (packages/studio-shared/src/studio-html.ts). Every mutating endpoint is refused in that mode.

Source

Thrown at packages/studio/src/api/install-package.ts:36

		withRequiredAuxiliaryPackages(dependencies);

	const browserStudioOperations = getBrowserStudioOperations();
	if (browserStudioOperations !== null) {
		const response =
			await browserStudioOperations.packageInstallation.installPackages({
				dependencies: dependenciesWithAuxiliaryPackages,
			});
		if (!response.success) {
			const error = new Error(response.reason);
			error.stack = response.stack;
			throw error;
		}

		return {};
	}

	if (window.remotion_isReadOnlyStudio) {
		throw new Error('installPackages() is not available in Read-Only Studio');
	}

	return callApi('/api/install-package', {
		dependencies: dependenciesWithAuxiliaryPackages,
	});
};

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Run Studio locally with its server (npx remotion studio) when you need package installation.
  2. In read-only deployments, hide the install affordance: check window.remotion_isReadOnlyStudio (or getRemotionEnvironment().isReadOnlyStudio) before rendering UI that calls installPackages().
  3. Pre-install dependencies into the project instead of installing them at runtime in read-only setups.
  4. Confirm you are not accidentally in Browser Studio mode - that path routes through browserStudioOperations earlier and has its own behavior.

Example fix

// before
import {installPackages} from '@remotion/studio';
installPackages([{name: 'lodash'}]); // throws in Read-Only Studio

// after
import {getRemotionEnvironment} from 'remotion';
import {installPackages} from '@remotion/studio';

if (getRemotionEnvironment().isStudio && !getRemotionEnvironment().isReadOnlyStudio) {
  installPackages([{name: 'lodash'}]);
} else {
  // read-only deployment: disable the button / show guidance instead
}
Defensive patterns

Strategy: validation

Validate before calling

import {getRemotionEnvironment} from 'remotion';

const env = getRemotionEnvironment();
if (env.isStudio && !env.isReadOnlyStudio) {
  await installPackages([{name: 'lodash'}]);
} else {
  // read-only deployment - hide/disable the install affordance
}

Type guard

import {getRemotionEnvironment} from 'remotion';

export const canInstallPackagesHere = (): boolean => {
  const env = getRemotionEnvironment();
  return env.isStudio && !env.isReadOnlyStudio;
};

Try / catch

try {
  await installPackages(deps);
} catch (err) {
  if (err.message.includes('Read-Only Studio')) {
    // statically deployed Studio - cannot install at runtime; guide the user to run Studio locally
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling installPackages() in a Studio that was statically deployed (no backing Studio server to run installs), or in an embed where the HTML was rendered with readOnlyStudio: true.

Common situations: Embedding Studio into another app as a static site; sharing previews from a deployed website build; testing Studio code against a static build instead of npx remotion studio.

Related errors


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-08-22). Data as JSON: /api/errors/7c2424db2885b734. Report an issue: GitHub.