Stirling-Tools/Stirling-PDF · error · Error

File "${file.name}" not found in storage

Error message

File "${file.name}" not found in storage

What it means

Thrown by downloadFileFromStorage when fileStorage.getStirlingFile(file.id) returns null/undefined — the IndexedDB storage layer could not find a stored file under that id. The file object passed in references storage by id, and the lookup failed, so there is no blob to download. The file's display name is interpolated into the message for user context.

Source

Thrown at frontend/editor/src/core/utils/downloadUtils.ts:29

 * @param filename - The filename for the download
 */
export function downloadBlob(blob: Blob, filename: string): void {
  void downloadFile({ data: blob, filename });
}

/**
 * Downloads a single file from IndexedDB storage
 * @param file - The file object with storage information
 * @throws Error if file cannot be retrieved from storage
 */
export async function downloadFileFromStorage(
  file: StirlingFileStub,
): Promise<void> {
  const lookupKey = file.id;
  const stirlingFile = await fileStorage.getStirlingFile(lookupKey);

  if (!stirlingFile) {
    throw new Error(`File "${file.name}" not found in storage`);
  }

  await downloadFileWithPolicy({
    data: stirlingFile,
    filename: stirlingFile.name,
    localPath: file.localFilePath,
    fileId: file.id,
  });
}

/**
 * Downloads multiple files as individual downloads
 * @param files - Array of files to download
 */
export async function downloadMultipleFiles(
  files: StirlingFileStub[],
): Promise<void> {
  for (const file of files) {

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Verify the file still exists in storage before offering the download action (call fileStorage.getStirlingFile and gate the UI).
  2. If the file was evicted, prompt the user to re-upload or re-run the operation that produced it.
  3. Increase the IndexedDB cache size or LRU limit if eviction is frequent.
  4. Ensure generated files are persisted to storage immediately after creation, not just held in memory.

Example fix

// before
await downloadFileFromStorage(file); // throws if evicted
// after
const stored = await fileStorage.getStirlingFile(file.id);
if (!stored) { notify('File no longer available. Please re-run the operation.'); return; }
await downloadFileFromStorage(file);
Defensive patterns

Strategy: validation

Validate before calling

import { fileStorage } from '@app/services/fileStorage';

async function isFileAvailable(file: StirlingFileStub): Promise<boolean> {
  return !!(await fileStorage.getStirlingFile(file.id));
}

if (!(await isFileAvailable(file))) {
  showUser('This file is no longer in storage. Please re-upload or re-run the operation.');
  return;
}

Type guard

async function resolveStoredFile(file: StirlingFileStub): Promise<File | null> {
  return await fileStorage.getStirlingFile(file.id);
}

Try / catch

try {
  await downloadFileFromStorage(file);
} catch (e) {
  if (e instanceof Error && e.message.includes('not found in storage')) {
    showUser(`'${file.name}' is no longer available. It may have been cleared from storage.`);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling downloadFileFromStorage(file) or downloadMultipleFiles([file]) where file.id does not correspond to any entry in IndexedDB. Happens if the file was evicted by the LRU cache, cleared by the user, stored under a different id, or never persisted (e.g. a generated preview that was not saved to storage).

Common situations: The IndexedDB LRU cache evicted a large/old file to make room. The user cleared site data / storage. A file id is stale (the FileContext still references a file that was removed). Private browsing or storage quota limits prevented persistence. A cross-tab race deleted the entry between listing and download.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/af8096eb5567d7f9. Report an issue: GitHub.