remotion-dev/remotion · error · Error

Invalid public file path: ${path}

Error message

Invalid public file path: ${path}

What it means

Browser Studio normalizes every public/static file path by stripping a single leading slash and then rejecting anything that is empty, contains a backslash, contains a NUL byte, or has any segment equal to '', '.' or '..'. This keeps public-file keys canonical and blocks path traversal / escapes. The throw happens during any operation that funnels a path through normalizePublicFilePath (canonicalization, add, rename, etc.).

Source

Thrown at packages/browser-studio/src/browser-studio-project-controller.ts:41

	fileName: string;
	mutate: (project: VirtualProject) => VirtualProject;
	nodePathMutationFiles: ProjectNodePathMutationFiles | null;
};

const MAX_HISTORY_ENTRIES = 100;

const normalizePublicFilePath = (path: string) => {
	const withoutLeadingSlash = path.startsWith('/') ? path.slice(1) : path;

	if (
		withoutLeadingSlash.length === 0 ||
		withoutLeadingSlash.includes('\\') ||
		withoutLeadingSlash.includes('\0') ||
		withoutLeadingSlash
			.split('/')
			.some((segment) => segment === '' || segment === '.' || segment === '..')
	) {
		throw new Error(`Invalid public file path: ${path}`);
	}

	return withoutLeadingSlash;
};

const getCanonicalPublicFiles = (project: VirtualProject) => {
	const canonicalFiles: Record<string, Uint8Array | string> = {};

	for (const [path, contents] of Object.entries(project.publicFiles ?? {})) {
		const canonicalPath = normalizePublicFilePath(path);
		if (Object.hasOwn(canonicalFiles, canonicalPath)) {
			throw new Error(`Multiple public files resolve to ${canonicalPath}`);
		}

		canonicalFiles[canonicalPath] = contents;
	}

	return canonicalFiles;

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Sanitize the path client-side before calling the operation: strip a leading '/', replace backslashes with '/', and reject empty/dot/dot-dot segments.
  2. Use forward-slash, single-segment-relative paths consistently (e.g. 'images/logo.png').
  3. Add a UI validation layer that mirrors these rules and disables the submit button on invalid input.
  4. If the path comes from user input, trim it and confirm it is non-empty before submission.

Example fix

// before
renameStaticFile({oldRelativePath: '/assets/../etc/file', newRelativePath: 'out'});

// after
const safe = (p: string) => p.replace(/^\//, '').replace(/\\/g, '/');
renameStaticFile({oldRelativePath: safe('assets/file'), newRelativePath: 'out'});
Defensive patterns

Strategy: validation

Validate before calling

const isValidPublicFilePath = (raw: string): boolean => {
  const p = raw.startsWith('/') ? raw.slice(1) : raw;
  if (p.length === 0 || p.includes('\\') || p.includes('\0')) return false;
  return p.split('/').every((seg) => seg !== '' && seg !== '.' && seg !== '..');
};
// guard every call site:
if (!isValidPublicFilePath(userPath)) throw new Error(`Refusing invalid path: ${userPath}`);

Type guard

const isCanonicalPublicPath = (p: string): boolean => {
  if (p.startsWith('/') || p.includes('\\') || p.includes('\0')) return false;
  return p.length > 0 && p.split('/').every((s) => s !== '' && s !== '.' && s !== '..');
};

Prevention

When it happens

Trigger: Calling a Browser Studio file operation with paths like '' (empty), '/' (becomes empty after strip), 'a//b' (empty segment), 'a/./b' or 'a/../b' (dot/dot-dot), 'a\\b' (Windows backslash), or a path containing a NUL character. Also when the UI forwards an untrimmed or programmatically-constructed string.

Common situations: Front-end passing a raw input without sanitizing; user typing a Windows-style path; code joining segments producing double slashes; accidental or malicious traversal attempts; trailing slashes producing an empty final segment.

Related errors


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