remotion-dev/remotion · critical · Error

Stored public file ${name} has no project storage

Error message

Stored public file ${name} has no project storage

What it means

Thrown by getObjectUrl in @remotion/browser-studio's project controller when a public file's contents are a 'stored' marker (isStoredPublicFile — the file lives in external storage, referenced by id) but `project.publicFileStorage` is null, so there is no way to fetch the bytes and build the object URL. It means the project was constructed with stored public files but no storage adapter was wired in, an embedding-host configuration mistake rather than a runtime condition.

Source

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

		contents: VirtualProjectPublicFile,
		project: VirtualProject,
	) => {
		const existing = objectUrls.get(name);
		if (arePublicFileContentsEqual(existing?.contents, contents)) {
			return existing!.url;
		}

		if (existing) {
			resolvedRevokeObjectUrl(existing.url);
		}

		const blob = isStoredPublicFile(contents)
			? await getBrowserStudioStoredPublicFile({
					file: contents,
					storage:
						project.publicFileStorage ??
						(() => {
							throw new Error(
								`Stored public file ${name} has no project storage`,
							);
						})(),
				})
			: new Blob([
					typeof contents === 'string' ? contents : contents.slice().buffer,
				]);
		const url = resolvedCreateObjectUrl(blob);
		objectUrls.set(name, {
			contents:
				typeof contents === 'string' || isStoredPublicFile(contents)
					? contents
					: contents.slice(),
			url,
		});
		return url;
	};

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Pass a `publicFileStorage` implementation when constructing the project/controller used by getObjectUrl
  2. If assets should be inline, re-save the public files with inline contents instead of stored markers
  3. On upgrade, check the changelog for publicFileStorage signature changes
  4. Catch the error per-file and surface which file name lacks storage instead of failing the whole render

Example fix

// before
const project = {
  ...restoredProject, // publicFiles contain stored-file entries
  publicFileStorage: null,
};

// after
const project = {
  ...restoredProject,
  publicFileStorage: {
    getFile: async (file) => myBackend.fetchAsset(file.storageId),
    putFile: async (file, bytes) => myBackend.putAsset(file.storageId, bytes),
  },
};
Defensive patterns

Strategy: validation

Validate before calling

const canServeStoredFiles = project.publicFileStorage !== null;
const hasStoredFiles = Object.values(project.publicFiles ?? {}).some(
  (f) => typeof f === 'object' && f !== null && 'type' in f && (f as {type?: string}).type === 'stored-public-file',
);
if (hasStoredFiles && !canServeStoredFiles) {
  throw new Error('Project contains stored public files but no publicFileStorage is configured');
}

Type guard

const hasPublicFileStorage = (
  project: VirtualProject,
): project is VirtualProject & {publicFileStorage: NonNullable<VirtualProject['publicFileStorage']>} =>
  project.publicFileStorage !== null;

Try / catch

try {
  const url = await getObjectUrl(name, contents, project);
} catch (error) {
  if (error instanceof Error && error.message.includes('has no project storage')) {
    // configuration bug: wire a publicFileStorage before rendering stored assets
  }
  throw error;
}

Prevention

When it happens

Trigger: Creating a project whose publicFiles contain stored-file entries while `publicFileStorage` is null/undefined; loading a persisted project archive with stored assets into a controller that was not given a storage implementation; storage adapter removed or renamed during an upgrade.

Common situations: Restoring a downloaded project (makeBrowserStudioProjectArchive) without re-registering the storage backend that served the original assets; version upgrade where publicFileStorage became a required parameter for stored assets; tests using serialized projects without a mock storage.

Related errors


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