{"record":{"id":"9b873fd08277b2e4","repo":"Stirling-Tools/Stirling-PDF","slug":"the-selected-file-is-no-longer-available","errorCode":null,"errorMessage":"The selected file is no longer available.","messagePattern":"The selected file is no longer available\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/contexts/FileContext.tsx","lineNumber":397,"sourceCode":"      return consumeFiles(\n        inputFileIds,\n        outputStirlingFiles,\n        outputStirlingFileStubs,\n        filesRef,\n        dispatch,\n        options,\n      );\n    },\n    [],\n  );\n\n  const runAutomaticPasswordRemoval = useCallback(\n    async (fileId: FileId, password: string): Promise<void> => {\n      const file = filesRef.current.get(fileId);\n      const parentStub = stateRef.current.files.byId[fileId];\n\n      if (!file || !parentStub) {\n        throw new Error(\n          t(\n            \"encryptedPdfUnlock.missingFile\",\n            \"The selected file is no longer available.\",\n          ),\n        );\n      }\n\n      const params: RemovePasswordParameters = { password };\n      const formData = buildRemovePasswordFormData(params, file);\n\n      const response = await apiClient.post(\n        \"/api/v1/security/remove-password\",\n        formData,\n        {\n          responseType: \"blob\",\n          suppressErrorToast: true, // Handle errors in modal UI instead of toast\n        },\n      );","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/contexts/FileContext.tsx#L379-L415","documentation":"Thrown in runAutomaticPasswordRemoval() when either the File object (from filesRef) or the parent stub (from stateRef.current.files.byId) is not found for the given fileId. Both are required: the File for building the form-data upload, and the stub for creating the unlocked child version. The message is i18n-localized via the encryptedPdfUnlock.missingFile key.","triggerScenarios":"The file was removed from FileContext (by user action or another tool) between when the password modal was opened and when the user submitted the password. The fileId passed to the function no longer exists in either the files Map or the stubs byId map.","commonSituations":"User closed or removed the file while the password entry modal was open. A concurrent operation consumed the file. Memory pressure evicted the file from the files Map but not the stub, or vice versa.","solutions":["Verify the file exists in FileContext before showing the password modal, and re-validate on submit.","Disable file removal/close while the password removal modal is open.","Use the existing suppressErrorToast pattern but add a modal-local error message for this case.","Check both filesRef and stateRef at submit time and show 'This file is no longer available' in the modal UI."],"exampleFix":"// before\nconst file = filesRef.current.get(fileId);\nconst parentStub = stateRef.current.files.byId[fileId];\nif (!file || !parentStub) {\n  throw new Error(t(\"encryptedPdfUnlock.missingFile\", \"The selected file is no longer available.\"));\n}\n\n// after\nconst file = filesRef.current.get(fileId);\nconst parentStub = stateRef.current.files.byId[fileId];\nif (!file || !parentStub) {\n  setModalError(t(\"encryptedPdfUnlock.missingFile\", \"The selected file is no longer available.\"));\n  return;\n}","handlingStrategy":"validation","validationCode":"// Re-validate file existence at submit time, not just at modal open\nconst file = filesRef.current.get(fileId);\nconst stub = stateRef.current.files.byId[fileId];\nif (!file || !stub) {\n  setModalError(t('encryptedPdfUnlock.missingFile', 'This file is no longer available.'));\n  return;\n}","typeGuard":"function fileExistsInContext(filesRef: React.MutableRefObject<Map<string, File>>, stateRef: React.MutableRefObject<FileState>, fileId: string): boolean {\n  return filesRef.current.has(fileId) && Boolean(stateRef.current.files.byId[fileId]);\n}","tryCatchPattern":null,"preventionTips":["Disable file removal and tab close while the password modal is open.","Re-validate file existence at modal submit, not just at modal open.","Use modal-local error state rather than throwing uncaught errors.","Clean up stale file IDs from the password modal when the underlying file is removed."],"tags":["file-context","password-removal","state-management","i18n","race-condition"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}