laurent22/joplin · error · Error
Missing read-write access. It might be necessary to share th
Error message
Missing read-write access. It might be necessary to share the folder with the application again.
What it means
Thrown by the web-worker RN fs-driver when a previously-saved directory handle no longer has the requested read-write permission and `requestPermission` also fails to grant it. Used to guard against silently writing to a folder the user has revoked access to. The fix the message suggests is re-sharing the folder.
Source
Thrown at packages/app-mobile/utils/fs-driver/fs-driver-rn.web.worker.ts:203
}
const saved = await this.accessHandleDatabase_.queryExternalHandle(path);
if (!saved) {
logger.debug('External lookup failed for', path);
return null;
}
const [handle, mode] = saved;
// At present, not all browsers support .queryPermission and .requestPermission on
// saved file handles.
if (!('queryPermission' in handle)) {
logger.warn('Browser does not support .queryPermission. Loading path: ', path);
return null;
}
const permission = { mode };
if (await handle.queryPermission(permission) !== 'granted' && await handle.requestPermission(permission) !== 'granted') {
throw new Error('Missing read-write access. It might be necessary to share the folder with the application again.');
}
this.externalHandles_.set(path, handle);
return handle;
}
private async pathToDirectoryHandle_(path: string, create = false): Promise<FileSystemDirectoryHandle|null> {
await this.initPromise_;
path = resolve('/', path);
if (path === '/') {
return this.fsRoot_;
} else if (`${path}/`.startsWith(externalDirectoryPrefix)) {
if (path === externalDirectoryPrefix || `${path}/` === externalDirectoryPrefix) {
// /external/ is virtual, it doesn't exist.
return null;
}
View on GitHub (pinned to 2654b33620)
Solutions
- Re-share the folder with the app via the directory picker (re-trigger `mountExternalDirectory`).
- Catch the error and surface a UI prompt asking the user to re-grant access.
- Before heavy operations, pre-check `handle.queryPermission({ mode: 'readwrite' })` and request early when state is 'prompt'.
- Detect unsupported browsers via the `'queryPermission' in handle` check and warn the user.
Example fix
// before
await driver.mountExternalDirectory(handle, id, 'readwrite');
// after
try {
await driver.mountExternalDirectory(handle, id, 'readwrite');
} catch (error) {
await showReShareFolderPrompt();
} Defensive patterns
Strategy: try-catch
Validate before calling
const granted =
!('queryPermission' in handle) ||
await handle.queryPermission({ mode }) === 'granted' ||
await handle.requestPermission({ mode }) === 'granted';
if (!granted) {
await showReShareFolderPrompt();
} Type guard
const hasPermissionApi = (h: unknown): h is FileSystemDirectoryHandle &
{ queryPermission(o: { mode: string }): Promise<string>;
requestPermission(o: { mode: string }): Promise<string> } =>
!!h && typeof (h as any).queryPermission === 'function'; Try / catch
try {
await driver.pathToDirectoryHandle_(path);
} catch (error) {
if (/Missing read-write access/i.test(error.message)) {
await showReShareFolderPrompt();
return;
}
throw error;
} Prevention
- Pre-check queryPermission and request early when state is 'prompt'.
- Re-prompt the user to re-share the folder on revocation.
- Detect unsupported browsers (no queryPermission) and warn the user.
When it happens
Trigger: The user previously granted a folder, then revoked permission via browser/site settings; the saved `FileSystemDirectoryHandle` is still cached but its permission state is 'denied' or 'prompt' and the prompt was dismissed/denied.
Common situations: Browser auto-expiry of granted permissions; user cleared site data; incognito session losing handle persistence; the browser does not support `queryPermission` (logged as a warning, not thrown).
Related errors
- ${mode} access is needed for ${id}.
- Could not read directory: ${path}: ${error.message}
- No model found at path: ${JSON.stringify(modelFolderPath)}
- Model not found at path ${modelPath}
- Error! Destination already exists
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/158a80f68ea09baf.
Report an issue: GitHub.