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
- Feature-detect with LocalFileService.isSupported() (or 'showDirectoryPicker' in window) before calling and show a fallback UI for unsupported browsers
- Serve the app over HTTPS or localhost so secure-context APIs are exposed
- In unsupported browsers, fall back to download/upload-based workflows or IndexedDB storage
- 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
- Feature-detect showDirectoryPicker before exposing local-storage features
- Serve over HTTPS or localhost (secure context required)
- Maintain a browser support matrix (Chrome/Edge yes; Firefox/Safari no) and test it
- Offer a non-API fallback storage mode in settings
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.