remotion-dev/remotion · error · Error

The bundle directory ${bundleDir} contains a symbolic link t

Error message

The bundle directory ${bundleDir} contains a symbolic link to a directory at ${path.relative(bundleDir, entryPath)}. Directory symbolic links are not supported by `deploySiteFromBundle()`.

What it means

Thrown by validateNoDirectorySymlinks(), called from validateBundleDir(), when recursing through the bundle directory tree and finding a symbolic link that resolves to a directory. deploySiteFromBundle() uploads flat files and cannot preserve directory symlinks, so any such link is rejected.

Source

Thrown at packages/lambda/src/shared/validate-bundle-dir.ts:31

	try {
		return JSON.parse(match[1]);
	} catch (error) {
		throw new Error(
			'Could not parse `window.remotion_publicPath` in the bundle index.html.',
			{cause: error},
		);
	}
};

const validateNoDirectorySymlinks = (
	directory: string,
	bundleDir: string,
): void => {
	for (const entry of fs.readdirSync(directory, {withFileTypes: true})) {
		const entryPath = path.join(directory, entry.name);
		if (entry.isSymbolicLink()) {
			if (fs.statSync(entryPath).isDirectory()) {
				throw new Error(
					`The bundle directory ${bundleDir} contains a symbolic link to a directory at ${path.relative(bundleDir, entryPath)}. Directory symbolic links are not supported by \`deploySiteFromBundle()\`.`,
				);
			}

			continue;
		}

		if (entry.isDirectory()) {
			validateNoDirectorySymlinks(entryPath, bundleDir);
		}
	}
};

export const validateBundleDir = (bundleDir: unknown): string => {
	if (typeof bundleDir !== 'string') {
		throw new TypeError(
			`The \`bundleDir\` must be a string, but received ${JSON.stringify(bundleDir)}.`,
		);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Resolve or copy real directories instead of symlinks before bundling (e.g. dereference with `cp -rL` or `fs.cpSync(..., {recursive: true})`).
  2. Audit the bundle with `find bundleDir -type l -exec test -d {} \; -print` and remove/replace offending links.
  3. Bundle with a tool that dereferences symlinks so the output tree is fully materialised.

Example fix

# before: deploySiteFromBundle({bundleDir: './out'})  # ./out/assets -> ../shared/assets
# after: materialise the bundle
# $ cp -rL out out-flat && deploySiteFromBundle({bundleDir: './out-flat'})
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs'
import path from 'node:path'
function assertNoDirectorySymlinks(dir) {
  for (const e of fs.readdirSync(dir, {withFileTypes: true})) {
    if (!e.isSymbolicLink()) continue
    if (fs.statSync(path.join(dir, e.name)).isDirectory())
      throw new Error(`Directory symlink found: ${e.name}`)
  }
}

Prevention

When it happens

Trigger: The bundleDir (or any subdirectory of it) contains a symlink whose target is a directory; common with node_modules-style links, monorepo workspace links, or manually created shortcuts.

Common situations: Bundling a path that includes symlinked node_modules (pnpm/yarn workspaces), symlinked asset folders, or running deploySiteFromBundle against a directory that contains dev conveniences like `assets -> ../shared/assets`.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/f03b0c99daf3ef53. Report an issue: GitHub.