remotion-dev/remotion · error

installPackages() is only available in the Studio

Error message

installPackages() is only available in the Studio

What it means

installPackages() from @remotion/studio installs npm packages by calling the Studio server's /api/install-package endpoint (or the Browser Studio operations bridge). It is a Studio-only API: when getRemotionEnvironment().isStudio is false - the code runs inside a regular render, the @remotion/player, or any plain React/Node app - it throws before doing anything.

Source

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

import type {
	InstallPackageResponse,
	PackageInstallSpec,
} from '@remotion/studio-shared';
import {getRemotionEnvironment} from 'remotion';
import {callApi} from '../components/call-api';
import {getBrowserStudioOperations} from '../helpers/browser-studio-operations';
import {withRequiredAuxiliaryPackages} from '../helpers/optional-package-dependencies';

export const installPackages = async (
	dependencies: readonly PackageInstallSpec[],
): Promise<InstallPackageResponse> => {
	if (!getRemotionEnvironment().isStudio) {
		throw new Error('installPackages() is only available in the Studio');
	}

	const dependenciesWithAuxiliaryPackages =
		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 {};

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Only call installPackages() from Studio-only surfaces (custom Studio UI registered for the Studio, not compositions that also render).
  2. Guard the call with getRemotionEnvironment().isStudio before invoking it.
  3. For programmatic package installation outside Studio, spawn your package manager (bun/npm/pnpm) directly instead of using this API.
  4. Audit import paths - pulling @remotion/studio into render-time code also bloats the render bundle.

Example fix

// before
import {installPackages} from '@remotion/studio';

export const install = () => installPackages([{name: 'lodash'}]); // throws outside Studio

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

export const install = () => {
  if (!getRemotionEnvironment().isStudio) {
    throw new Error('Package installation is only available inside Remotion Studio');
  }
  return installPackages([{name: 'lodash'}]);
};
Defensive patterns

Strategy: type-guard

Validate before calling

import {getRemotionEnvironment} from 'remotion';

if (!getRemotionEnvironment().isStudio) {
  // do not call installPackages() here - it throws outside Studio
} else {
  await installPackages([{name: 'lodash'}]);
}

Type guard

import {getRemotionEnvironment} from 'remotion';

export const canInstallPackages = (): boolean =>
  getRemotionEnvironment().isStudio;

Try / catch

try {
  await installPackages(deps);
} catch (err) {
  if (err.message.includes('only available in the Studio')) {
    // called outside Studio - skip or route to a package manager directly
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Importing installPackages from '@remotion/studio' inside a composition, a hook that also executes during rendering, or a Node script; calling it from a preview embedded outside Studio.

Common situations: Sharing a utility module between Studio toolbar components and video compositions; copying Studio example code into a Player app; SSR builds that execute the module outside the Studio environment.

Related errors


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