koodo-reader/koodo-reader · error · Error

File System Access API not supported

Error message

File System Access API not supported

What it means

LocalFileService wraps the browser File System Access API for storing books/covers locally. requestDirectoryAccess() throws 'File System Access API not supported' when window.showDirectoryPicker is undefined, i.e. the runtime does not implement the API (isSupported() is false). It is thrown inside the try block, so callers receive it as a rejection rather than a null handle.

Source

Thrown at src/utils/file/localFile.ts:78

        // Fallback: try to read a property; may still throw for invalid handle
        void handle.name;
      }
      return true;
    } catch {
      return false;
    }
  }

  // 检查浏览器是否支持 File System Access API
  static isSupported(): boolean {
    return "showDirectoryPicker" in window;
  }

  // 请求目录访问权限
  static async requestDirectoryAccess(): Promise<FileSystemDirectoryHandle | null> {
    try {
      if (!this.isSupported()) {
        throw new Error("File System Access API not supported");
      }

      const directoryHandle = await (window as any).showDirectoryPicker({
        mode: "readwrite",
        startIn: "documents",
      });

      // 存储权限句柄到 IndexedDB
      await this.storeDirectoryHandle(directoryHandle);
      this.directoryHandle = directoryHandle;

      return directoryHandle;
    } catch (error) {
      console.error("Error requesting directory access:", error);
      return null;
    }
  }
  // 添加用户友好的权限状态检查方法

View on GitHub (pinned to 7d40df41e0)

Solutions

  1. Feature-detect with LocalFileService.isSupported() (or 'showDirectoryPicker' in window) before calling and show a fallback UI for unsupported browsers
  2. Serve the app over HTTPS or localhost so secure-context APIs are exposed
  3. In unsupported browsers, fall back to download/upload-based workflows or IndexedDB storage
  4. If in Electron, ensure the Chromium version is recent enough to include showDirectoryPicker

Example fix

// before
const handle = await LocalFileService.requestDirectoryAccess();
// after
if (!LocalFileService.isSupported()) {
  alert("Your browser does not support local directory access.");
} else {
  const handle = await LocalFileService.requestDirectoryAccess();
}
Defensive patterns

Strategy: fallback

Validate before calling

if (!("showDirectoryPicker" in window)) {
  // unsupported — route to fallback UI
}
if (!window.isSecureContext) {
  // API hidden on insecure origins
}

Type guard

function supportsFileSystemAccess(w: Window = window): w is Window & { showDirectoryPicker: (o?: any) => Promise<FileSystemDirectoryHandle> } {
  return "showDirectoryPicker" in w;
}

Try / catch

try {
  const handle = await LocalFileService.requestDirectoryAccess();
} catch (e) {
  if (e.message === "File System Access API not supported") {
    enableFallbackStorage(); // download/upload or IndexedDB mode
  } else throw e;
}

Prevention

When it happens

Trigger: Calling requestDirectoryAccess() in Firefox/Safari (no showDirectoryPicker), in mobile browsers, in non-secure contexts (the API requires HTTPS or localhost), or in Electron/iframe environments where the picker is unavailable.

Common situations: Users on Firefox or Safari trying to enable local storage sync, deploying the app over plain HTTP so secure-context-only APIs are hidden, or embedded webviews lacking the picker.

Related errors


AI-assisted analysis of koodo-reader/koodo-reader@7d40df41e0 (2026-08-29). Data as JSON: /api/errors/934cfb008bdc9ffd. Report an issue: GitHub.