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
- No functional breakage — the theme applies for the session; only persistence is skipped.
- Clear other localStorage keys on the origin if quota is genuinely exhausted.
- Allow site data for the origin to restore persistence.
- 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
- Keep the state update outside the try block so a storage failure never blocks the UI change.
- Detect QuotaExceededError by name and prune old keys before retrying once.
- Test theming in a private window — it is the fastest way to catch storage-dependent UI bugs.
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
- Missing cwd in FileEdit hook input for session ${sessionId},
- bun install failed in ${targetDir} ${describeExecError(err)}
- fileEditHandler requires filePath
- Observation TV UI not found at any expected location
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/6299eb14a79cef04.
Report an issue: GitHub.