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

  1. Re-share the folder with the app via the directory picker (re-trigger `mountExternalDirectory`).
  2. Catch the error and surface a UI prompt asking the user to re-grant access.
  3. Before heavy operations, pre-check `handle.queryPermission({ mode: 'readwrite' })` and request early when state is 'prompt'.
  4. 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

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


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/158a80f68ea09baf. Report an issue: GitHub.