thedotmack/claude-mem · warning

npmPackageRootDirectory: expected package.json at ${root}. B

Error message

npmPackageRootDirectory: expected package.json at ${root}. Bundle structure may have changed — update the path walk.

What it means

setThemePreference writes the chosen theme to localStorage; if setItem throws (QuotaExceededError in private browsing or full storage, SecurityError when storage is blocked) the message is console.warn'd but setPreference still runs — the theme applies in-memory for the session and simply won't survive a reload. Same storage-unavailability family as the read warning, but on the write path.

Source

Thrown at src/npx-cli/utils/paths.ts:44

}

export function installedPluginsPath(): string {
  return join(pluginsDirectory(), 'installed_plugins.json');
}

export function claudeSettingsPath(): string {
  return join(claudeConfigDirectory(), 'settings.json');
}

export function pluginCacheDirectory(version: string): string {
  return join(pluginsDirectory(), 'cache', 'thedotmack', 'claude-mem', version);
}

export function npmPackageRootDirectory(): string {
  const currentFilePath = fileURLToPath(import.meta.url);
  const root = join(dirname(currentFilePath), '..', '..');
  if (!existsSync(join(root, 'package.json'))) {
    throw new Error(
      `npmPackageRootDirectory: expected package.json at ${root}. ` +
      `Bundle structure may have changed — update the path walk.`,
    );
  }
  return root;
}

export function npmPackagePluginDirectory(): string {
  return join(npmPackageRootDirectory(), 'plugin');
}

export function readPluginVersion(): string {
  const pluginJsonPath = join(npmPackagePluginDirectory(), '.claude-plugin', 'plugin.json');
  if (existsSync(pluginJsonPath)) {
    try {
      const pluginJson = JSON.parse(readFileSync(pluginJsonPath, 'utf-8'));
      if (pluginJson.version) return pluginJson.version;
    } catch {

View on GitHub (pinned to e2d1df569a)

Solutions

  1. No functional breakage — the theme applies for the session; only persistence is skipped.
  2. Clear other localStorage keys on the origin if quota is genuinely exhausted.
  3. Allow site data for the origin to restore persistence.
  4. Detect repeated failures and switch to a cookie or in-memory-only mode deliberately.
Defensive patterns

Strategy: try-catch

Try / catch

const setThemePreference = (newPreference: ThemePreference) => {
  try {
    localStorage.setItem(STORAGE_KEY, newPreference);
  } catch (e: unknown) {
    // Private mode / quota / blocked storage: apply in-memory anyway so UI still works
    console.warn('Failed to save theme preference to localStorage:', e instanceof Error ? e.message : String(e));
  }
  setPreference(newPreference); // ALWAYS runs — persistence is optional, state change is not
};

Prevention

When it happens

Trigger: Safari/Chrome private windows where setItem throws; storage quota exhausted by other keys; embedded context with storage blocked; browser settings forbidding site data.

Common situations: Incognito users toggling dark mode; iframe-embedded viewers with partitioned storage; devices with tiny storage quotas.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/6299eb14a79cef04. Report an issue: GitHub.