Stirling-Tools/Stirling-PDF · error · Error

The selected file is no longer available.

Error message

The selected file is no longer available.

What it means

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.

Source

Thrown at frontend/editor/src/core/contexts/FileContext.tsx:397

      return consumeFiles(
        inputFileIds,
        outputStirlingFiles,
        outputStirlingFileStubs,
        filesRef,
        dispatch,
        options,
      );
    },
    [],
  );

  const runAutomaticPasswordRemoval = useCallback(
    async (fileId: FileId, password: string): Promise<void> => {
      const file = filesRef.current.get(fileId);
      const parentStub = stateRef.current.files.byId[fileId];

      if (!file || !parentStub) {
        throw new Error(
          t(
            "encryptedPdfUnlock.missingFile",
            "The selected file is no longer available.",
          ),
        );
      }

      const params: RemovePasswordParameters = { password };
      const formData = buildRemovePasswordFormData(params, file);

      const response = await apiClient.post(
        "/api/v1/security/remove-password",
        formData,
        {
          responseType: "blob",
          suppressErrorToast: true, // Handle errors in modal UI instead of toast
        },
      );

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Verify the file exists in FileContext before showing the password modal, and re-validate on submit.
  2. Disable file removal/close while the password removal modal is open.
  3. Use the existing suppressErrorToast pattern but add a modal-local error message for this case.
  4. Check both filesRef and stateRef at submit time and show 'This file is no longer available' in the modal UI.

Example fix

// before
const file = filesRef.current.get(fileId);
const parentStub = stateRef.current.files.byId[fileId];
if (!file || !parentStub) {
  throw new Error(t("encryptedPdfUnlock.missingFile", "The selected file is no longer available."));
}

// after
const file = filesRef.current.get(fileId);
const parentStub = stateRef.current.files.byId[fileId];
if (!file || !parentStub) {
  setModalError(t("encryptedPdfUnlock.missingFile", "The selected file is no longer available."));
  return;
}
Defensive patterns

Strategy: validation

Validate before calling

// Re-validate file existence at submit time, not just at modal open
const file = filesRef.current.get(fileId);
const stub = stateRef.current.files.byId[fileId];
if (!file || !stub) {
  setModalError(t('encryptedPdfUnlock.missingFile', 'This file is no longer available.'));
  return;
}

Type guard

function fileExistsInContext(filesRef: React.MutableRefObject<Map<string, File>>, stateRef: React.MutableRefObject<FileState>, fileId: string): boolean {
  return filesRef.current.has(fileId) && Boolean(stateRef.current.files.byId[fileId]);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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