{"record":{"id":"6323fe94b9847891","repo":"Stirling-Tools/Stirling-PDF","slug":"parent-stub-not-found","errorCode":null,"errorMessage":"Parent stub not found","messagePattern":"Parent stub not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/components/viewer/EmbedPdfViewer.tsx","lineNumber":643,"sourceCode":"\n      // Step 1: Export PDF with annotations using EmbedPDF\n      const arrayBuffer = await exportActions.saveAsCopy();\n      if (!arrayBuffer) {\n        throw new Error(\"Failed to export PDF\");\n      }\n\n      // Step 2: Convert ArrayBuffer to File\n      const blob = new Blob([arrayBuffer], { type: \"application/pdf\" });\n      const filename = currentFile.name || \"document.pdf\";\n      const file = new File([blob], filename, { type: \"application/pdf\" });\n\n      // Step 3: Create StirlingFiles and stubs for version history\n      // Only consume the current file, not all active files\n      const currentFileId = currentFileStableId;\n      if (!currentFileId) throw new Error(\"Current file ID not found\");\n\n      const parentStub = selectors.getStirlingFileStub(currentFileId);\n      if (!parentStub) throw new Error(\"Parent stub not found\");\n\n      const { stirlingFiles, stubs } = await createStirlingFilesAndStubs(\n        [file],\n        parentStub,\n        selectedTool ?? \"multiTool\",\n      );\n\n      // Store the page to restore after file replacement triggers re-render\n      pendingScrollRestoreRef.current = pageToRestore;\n      scrollRestoreAttemptsRef.current = 0;\n\n      // Store the rotation to restore after file replacement\n      pendingRotationRestoreRef.current = currentRotation;\n      rotationRestoreAttemptsRef.current = 0;\n      // Track the new file ID so the viewer follows it after the list reorders\n      const newFileId = stubs[0]?.id;\n      if (newFileId) setActiveFileId(newFileId);\n","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/components/viewer/EmbedPdfViewer.tsx#L625-L661","documentation":"Thrown in EmbedPdfViewer's export path when selectors.getStirlingFileStub(currentFileId) returns null. The stub is the FileContext's metadata record (parent version, operation history) for the file. Without it, createStirlingFilesAndStubs() cannot establish parent-child version lineage for the exported copy.","triggerScenarios":"The file's stub was evicted from in-memory state (FileContext reducer), the stub was never created for this file (e.g., file loaded via a non-standard path), or the currentFileId doesn't match any stub due to ID mismatch.","commonSituations":"IndexedDB cache eviction under memory pressure removed the stub. File was loaded via drag-and-drop or external route that bypassed stub creation. A previous consumeFiles operation removed the stub while the viewer still held the file.","solutions":["Verify the stub exists before starting the export: const stub = selectors.getStirlingFileStub(currentFileId); if (!stub) { /* recreate or abort */ }.","If the stub is missing, create a fresh one via createStirlingFileStub before proceeding with the export.","Add a selector that checks stub existence reactively and disables export when false.","Log the currentFileId and list of known stub IDs when this hits to diagnose eviction vs mismatch."],"exampleFix":"// before\nconst parentStub = selectors.getStirlingFileStub(currentFileId);\nif (!parentStub) throw new Error(\"Parent stub not found\");\n\n// after\nconst parentStub = selectors.getStirlingFileStub(currentFileId);\nif (!parentStub) {\n  console.error(\"Stub not found for file\", currentFileId, \"known stubs:\", Object.keys(stateRef.current.files.byId));\n  setErrorMessage(\"File metadata is missing. Reloading the file may fix this.\");\n  return;\n}","handlingStrategy":"validation","validationCode":"// Verify stub exists before starting the export workflow\nconst stub = selectors.getStirlingFileStub(currentFileId);\nif (!stub) {\n  console.error('No stub for file', currentFileId, '. Known:', Object.keys(stateRef.current.files.byId));\n  setErrorMessage('File metadata is missing. Please reload the file.');\n  return;\n}","typeGuard":"function hasFileStub(selectors: FileContextSelectors, fileId: string): boolean {\n  const stub = selectors.getStirlingFileStub(fileId);\n  return stub !== null && stub !== undefined && typeof stub.id === 'string';\n}","tryCatchPattern":null,"preventionTips":["Check stub existence before entering any async export workflow.","Log known stub IDs alongside the missing ID to distinguish eviction from mismatch.","Avoid file removal operations while export is in progress.","Consider pinning stubs in state while a file is actively being viewed/edited."],"tags":["file-context","stubs","state-management","viewer","version-history"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}