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
- Pass a `publicFileStorage` implementation when constructing the project/controller used by getObjectUrl
- If assets should be inline, re-save the public files with inline contents instead of stored markers
- On upgrade, check the changelog for publicFileStorage signature changes
- 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
- Always construct the project with a publicFileStorage adapter when assets are stored externally
- After restoring project archives, assert storage is configured before first render
- Add an integration test that loads a serialized project and renders a stored asset
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
- You have multiple buckets (${remotionBuckets .map((b) =>
- OPFS is not available in this browser
- Invalid public file path: ${path}
- ${oldRelativePath} does not exist
- ${newRelativePath} already exists
AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-08-22).
Data as JSON: /api/errors/add03bf61930b117.
Report an issue: GitHub.