{"record":{"id":"c3eca5ca7648ebc7","repo":"Stirling-Tools/Stirling-PDF","slug":"file-not-found-in-storage-filestub-name-id","errorCode":null,"errorMessage":"File not found in storage: ${fileStub.name} (ID: ${fileStub.id})","messagePattern":"File not found in storage: (.+?) \\(ID: (.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/hooks/useFileManager.ts","lineNumber":93,"sourceCode":"      return fallback;\n    },\n    [],\n  );\n\n  const convertToFile = useCallback(\n    async (fileStub: StirlingFileStub): Promise<File> => {\n      if (!indexedDB) {\n        throw new Error(\"IndexedDB context not available\");\n      }\n\n      // Regular file loading\n      if (fileStub.id) {\n        const file = await indexedDB.loadFile(fileStub.id);\n        if (file) {\n          return file;\n        }\n      }\n      throw new Error(\n        `File not found in storage: ${fileStub.name} (ID: ${fileStub.id})`,\n      );\n    },\n    [indexedDB],\n  );\n\n  const loadRecentFiles = useCallback(async (): Promise<StirlingFileStub[]> => {\n    setLoading(true);\n    try {\n      if (!indexedDB) {\n        return [];\n      }\n\n      // Load only leaf files metadata (processed files that haven't been used as input for other tools)\n      const stirlingFileStubs = await fileStorage.getLeafStirlingFileStubs();\n      const remoteIdSet = new Set(\n        stirlingFileStubs\n          .map((stub) => stub.remoteStorageId)","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/hooks/useFileManager.ts#L75-L111","documentation":"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).","triggerScenarios":"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.","commonSituations":"Long sessions with many large files triggering LRU eviction; restored session state pointing at deleted files; browser storage cleanup under pressure.","solutions":["Re-add the file from disk when its storage is missing rather than hard-failing.","Increase the IndexedDB LRU cap so working-set files are not evicted.","Validate stubs against storage on mount and prune dangling stubs from UI state proactively.","Show a user-facing message naming the missing file so the user knows which file to re-add."],"exampleFix":"// before\nconst file = await indexedDB.loadFile(fileStub.id);\nif (file) return file;\nthrow new Error(`File not found in storage: ${fileStub.name} (ID: ${fileStub.id})`);\n\n// after — prune the dangling stub and surface a recoverable message\nconst file = await indexedDB.loadFile(fileStub.id);\nif (file) return file;\nremoveStubFromState?.(fileStub.id);\nthrow new Error(`File not found in storage: ${fileStub.name}. It may have been removed — please re-add it.`);","handlingStrategy":"validation","validationCode":"// Confirm the file is still persisted before attempting conversion\nconst exists = fileStub.id ? await indexedDB?.hasFile?.(fileStub.id) : false;\nif (!exists) {\n  // prune the stub from UI state and prompt re-add; do not call convertToFile\n}","typeGuard":"function isStoredFile(f: File | null | undefined): f is File { return f instanceof File; }","tryCatchPattern":"try {\n  return await convertToFile(stub);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith(\"File not found in storage:\")) {\n    // prune dangling stub, prompt user to re-add\n  } else throw e;\n}","preventionTips":["Validate stubs against storage on mount and prune dangling ones from UI state.","Raise the IndexedDB LRU cap so working-set files are not evicted.","Prompt the user to re-add the file when storage is missing."],"tags":["indexeddb","eviction","file-storage","stale-state"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}