koala73/worldmonitor · error

Settings export could not read browser storage.

Error message

Settings export could not read browser storage.

What it means

exportSettings builds a settings backup from a snapshot of the browser's storage (localStorage etc.) taken by safeStorageSnapshot(). If any underlying storage read throws — the snapshot reports ok=false rather than degrading to an empty backup — exportSettings throws so it never ships a backup that silently looks successful but is empty.

Solutions

  1. Detect storage availability up front (try a test localStorage read) and show the user an explanatory message with browser-settings guidance before exporting.
  2. Catch this error in the UI and offer an alternative export path (e.g. export current in-memory settings state instead of storage-backed values).
  3. If running in an iframe, ensure the document has storage access (requestStorageAccess / proper permissions policy) or export from a top-level context.
  4. Retry the export once after the user adjusts browser settings and storage becomes readable.

Example fix

// before
const backup = exportSettings(); // throws when storage is blocked
// after
let backup;
try {
  backup = exportSettings();
} catch (err) {
  if (err instanceof Error && err.message.includes('could not read browser storage')) {
    notifyUser('Browser storage is blocked; enable site data or export current settings instead.');
    backup = buildBackupFromInMemoryState();
  } else throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function storageIsReadable(): boolean {
  try {
    const k = '__wm_probe__';
    window.localStorage.setItem(k, '1');
    window.localStorage.removeItem(k);
    return true;
  } catch {
    return false;
  }
}
if (!storageIsReadable()) warnUserBeforeExport();

Try / catch

try {
  const backup = exportSettings();
} catch (err) {
  if (err instanceof Error && err.message === 'Settings export could not read browser storage.') {
    showStorageBlockedDialog(); // guide user to enable site data, or export in-memory state
  } else throw err;
}

Prevention

When it happens

Trigger: Calling exportSettings when browser storage is unreadable: localStorage access blocked (browser privacy mode / 'Block all cookies'), StorageDisabled SecurityError in sandboxed iframes, quota/state errors, or storage poisoned by an extension that throws on property access.

Common situations: Users on strict privacy settings or Brave/Safari locking down storage; the app embedded in a third-party iframe with partitioned storage; automated headless browsers denying storage; corporate policies disabling site data.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/ba7b29c6143a4ba2. Report an issue: GitHub.

Appendix: source

Thrown at src/utils/settings-persistence.ts:62

export function exportSettings(): void {
  const data: Record<string, string> = {};

  // Storage that cannot be read has no settings to export, and handing the
  // user a downloadable file anyway is worse than failing: the caller in
  // preferences-content.ts wraps this in try/catch and shows `exportSuccess`
  // when it returns, so a silent empty payload becomes a green "Exported"
  // toast over a backup containing nothing (#7833 review). Stay loud.
  //
  // Testing AVAILABILITY is not enough on its own, which an earlier round of
  // this fix got wrong: a handle can exist while enumeration or an individual
  // read throws, and the degrading accessors then return `[]`/`null` and
  // rebuild exactly that empty-but-successful backup. The snapshot reports
  // whether the reads themselves succeeded, so a partial one fails instead of
  // shipping a backup the user would only discover was empty when restoring.
  const snapshot = safeStorageSnapshot();
  if (!snapshot.ok) {
    throw new Error('Settings export could not read browser storage.');
  }

  let variant = 'full';
  for (const [key, value] of snapshot.entries) {
    if (key === 'worldmonitor-variant' && value) variant = value;
    if (isSettingsKey(key)) data[key] = value;
  }

  const exportData: ExportedSettings = {
    version: 1,
    timestamp: new Date().toISOString(),
    variant,
    data,
  };

  const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');

View on GitHub (pinned to 7d06c8633d)