Stirling-Tools/Stirling-PDF · error · Error

File not found in storage: ${fileStub.name} (ID: ${fileStub.

Error message

File not found in storage: ${fileStub.name} (ID: ${fileStub.id})

What it means

Thrown by `convertToFile` when a fileStub has an id but `indexedDB.loadFile(id)` returns null/undefined — the id no longer resolves to a stored File. The stub exists in UI state, but the underlying blob was removed from IndexedDB (eviction, manual clear, or never persisted).

Source

Thrown at frontend/editor/src/core/hooks/useFileManager.ts:93

      return fallback;
    },
    [],
  );

  const convertToFile = useCallback(
    async (fileStub: StirlingFileStub): Promise<File> => {
      if (!indexedDB) {
        throw new Error("IndexedDB context not available");
      }

      // Regular file loading
      if (fileStub.id) {
        const file = await indexedDB.loadFile(fileStub.id);
        if (file) {
          return file;
        }
      }
      throw new Error(
        `File not found in storage: ${fileStub.name} (ID: ${fileStub.id})`,
      );
    },
    [indexedDB],
  );

  const loadRecentFiles = useCallback(async (): Promise<StirlingFileStub[]> => {
    setLoading(true);
    try {
      if (!indexedDB) {
        return [];
      }

      // Load only leaf files metadata (processed files that haven't been used as input for other tools)
      const stirlingFileStubs = await fileStorage.getLeafStirlingFileStubs();
      const remoteIdSet = new Set(
        stirlingFileStubs
          .map((stub) => stub.remoteStorageId)

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Re-add the file from disk when its storage is missing rather than hard-failing.
  2. Increase the IndexedDB LRU cap so working-set files are not evicted.
  3. Validate stubs against storage on mount and prune dangling stubs from UI state proactively.
  4. Show a user-facing message naming the missing file so the user knows which file to re-add.

Example fix

// before
const file = await indexedDB.loadFile(fileStub.id);
if (file) return file;
throw new Error(`File not found in storage: ${fileStub.name} (ID: ${fileStub.id})`);

// after — prune the dangling stub and surface a recoverable message
const file = await indexedDB.loadFile(fileStub.id);
if (file) return file;
removeStubFromState?.(fileStub.id);
throw new Error(`File not found in storage: ${fileStub.name}. It may have been removed — please re-add it.`);
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the file is still persisted before attempting conversion
const exists = fileStub.id ? await indexedDB?.hasFile?.(fileStub.id) : false;
if (!exists) {
  // prune the stub from UI state and prompt re-add; do not call convertToFile
}

Type guard

function isStoredFile(f: File | null | undefined): f is File { return f instanceof File; }

Try / catch

try {
  return await convertToFile(stub);
} catch (e) {
  if (e instanceof Error && e.message.startsWith("File not found in storage:")) {
    // prune dangling stub, prompt user to re-add
  } else throw e;
}

Prevention

When it happens

Trigger: LRU cache eviction removed the file to make room for newer uploads; user cleared site data; a previous session's stubs were restored (e.g. from URL/history) without their storage; the file failed to persist originally and only a stub survived.

Common situations: Long sessions with many large files triggering LRU eviction; restored session state pointing at deleted files; browser storage cleanup under pressure.

Related errors


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