{"record":{"id":"37f61f538ecc0d98","repo":"Stirling-Tools/Stirling-PDF","slug":"incremental-export-failed-for-cached-document-ple","errorCode":null,"errorMessage":"Incremental export failed for cached document. Please reload and retry.","messagePattern":"Incremental export failed for cached document\\. Please reload and retry\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/tools/pdfTextEditor/PdfTextEditor.tsx","lineNumber":1359,"sourceCode":"\n            const contentDisposition =\n              response.headers?.[\"content-disposition\"] ?? \"\";\n            const detectedName = getFilenameFromHeaders(contentDisposition);\n            const downloadName = detectedName || expectedName;\n\n            downloadBlob(response.data, downloadName);\n\n            if (onComplete && !skipComplete) {\n              const pdfFile = new File([response.data], downloadName, {\n                type: \"application/pdf\",\n              });\n              onComplete([pdfFile]);\n            }\n            setErrorMessage(null);\n            return;\n          } catch (incrementalError) {\n            if (isLazyMode && cachedJobIdRef.current) {\n              throw new Error(\n                \"Incremental export failed for cached document. Please reload and retry.\",\n                {\n                  cause: incrementalError,\n                },\n              );\n            }\n            console.warn(\n              \"[handleGeneratePdf] Incremental export failed, falling back to full export\",\n              incrementalError,\n            );\n          }\n        }\n\n        if (isLazyMode && totalPages > 0) {\n          const allPageIndices = Array.from(\n            { length: totalPages },\n            (_, index) => index,\n          );","sourceCodeStart":1341,"sourceCodeEnd":1377,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/tools/pdfTextEditor/PdfTextEditor.tsx#L1341-L1377","documentation":"Thrown in handleGeneratePdf when the incremental export (partial/{cachedJobId} endpoint) fails and the code is in lazy mode with a cached jobId. Unlike non-lazy mode (which falls back to full export), lazy mode throws because the full export would require loading all page images first, which is expensive. The original error is attached as cause.","triggerScenarios":"The cached jobId expired on the server (job retention TTL exceeded). The server restarted and lost the cached document state. The partial export endpoint returned an error (corrupt cache state, server bug). The document changed so significantly that the incremental patch is invalid.","commonSituations":"User edited a document, left it idle for a long time, then tried to export — the cached job expired. Server redeployed between conversion and export. Network instability during the partial export request.","solutions":["Clear the cached jobId (cachedJobIdRef.current = null) and reload the document to get a fresh conversion.","Fall back to full export despite the cost — load all page images and send the complete document.","Catch this specific error in the UI and show a 'Document cache expired, reloading...' message with automatic reload.","Refresh the cached job periodically if the document is open for a long time."],"exampleFix":"// before\n} catch (incrementalError) {\n  if (isLazyMode && cachedJobIdRef.current) {\n    throw new Error(\"Incremental export failed for cached document. Please reload and retry.\", {\n      cause: incrementalError,\n    });\n  }\n  // fall back to full export\n}\n\n// after\n} catch (incrementalError) {\n  if (isLazyMode && cachedJobIdRef.current) {\n    console.warn(\"Incremental export failed, falling back to full export\", incrementalError);\n    cachedJobIdRef.current = null;\n    // Fall through to full export below\n  }\n}","handlingStrategy":"fallback","validationCode":"// Check cached job validity before attempting incremental export\nif (isLazyMode && cachedJobIdRef.current) {\n  // Verify the job still exists\n  try {\n    await apiClient.get(`/api/v1/general/job/${cachedJobIdRef.current}`);\n  } catch {\n    // Job expired — clear cache and use full export\n    cachedJobIdRef.current = null;\n  }\n}","typeGuard":null,"tryCatchPattern":"} catch (incrementalError) {\n  if (isLazyMode && cachedJobIdRef.current) {\n    // Instead of throwing, fall back to full export\n    console.warn('[handleGeneratePdf] Incremental export failed, falling back to full export', incrementalError);\n    cachedJobIdRef.current = null;\n    // Fall through to full export code below\n  }\n}","preventionTips":["Clear cachedJobId on incremental failure and fall back to full export.","Periodically verify the cached job still exists on the server (heartbeat).","Show a user-facing message when falling back: 'Using full export mode — this may take longer.'","Set a client-side TTL on cachedJobId matching the server's job retention period."],"tags":["pdf-text-editor","incremental-export","lazy-mode","export","cache-expiry"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}