thedotmack/claude-mem · warning

[uninstall] Could not rewrite

Error message

[uninstall] Could not rewrite ${filePath}:

What it means

During uninstall, stripLegacyClaudeMemAlias scans shell rc files for legacy claude-mem alias lines and rewrites them with writeFileSync. When the rewrite throws (read-only file, permissions, disk error), the function logs this warning instead of failing the uninstall, since alias removal is best-effort cleanup. The uninstall continues normally.

Solutions

  1. Check and fix permissions on the reported rc file: chown yourself and chmod u+w.
  2. Manually remove the legacy alias line from the file (search for 'claude-mem' alias).
  3. Re-run the uninstall with sufficient privileges (e.g. sudo) if the file is root-owned.
  4. Free disk space if the cause is ENOSPC and re-run uninstall.

Example fix

// before (read-only rc file blocks rewrite)
try { writeFileSync(filePath, filtered.join('\n')); } catch { warn(...); }
// after (pre-check writability and report clearly)
if (accessSync(filePath, W_OK) !== undefined) {
  writeFileSync(filePath, filtered.join('\n'));
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { accessSync, constants } from 'fs';
try { accessSync(filePath, constants.W_OK); } catch { console.warn(`Skipping read-only file: ${filePath}`); }

Type guard

function isWritableError(e: unknown): e is NodeJS.ErrnoException {
  return e instanceof Error && 'code' in e && ['EACCES','EROFS','ENOSPC'].includes((e as NodeJS.ErrnoException).code ?? '');
}

Try / catch

try {
  writeFileSync(filePath, filtered.join('\n'));
} catch (e) {
  if (isWritableError(e)) console.warn(`Cannot write ${filePath}: ${e.code} — fix permissions and re-run`);
  else throw e;
}

Prevention

When it happens

Trigger: writeFileSync(filePath, filtered.join('\n')) throws inside the try block — i.e. the rc file matched alias lines but could not be written back (EACCES, EROFS, ENOSPC, or the file was made read-only between read and write).

Common situations: Shell rc files owned by root or another user while running the uninstaller under a different account; dotfiles synced with immutable/read-only flags; a full disk; an editor holding the file with restrictive locking on unusual filesystems.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/1dc674a514a53292. Report an issue: GitHub.

Appendix: source

Thrown at src/npx-cli/commands/uninstall.ts:127

  const aliasLineRegex = /^\s*alias\s+claude-mem\s*=/;

  for (const filePath of candidateFiles) {
    if (!existsSync(filePath)) continue;
    let content: string;
    try {
      content = readFileSync(filePath, 'utf-8');
    } catch (error: unknown) {
      console.warn(`[uninstall] Could not read ${filePath}:`, error instanceof Error ? error.message : String(error));
      continue;
    }
    const lines = content.split('\n');
    const filtered = lines.filter((line) => !aliasLineRegex.test(line));
    if (filtered.length === lines.length) continue; 
    try {
      writeFileSync(filePath, filtered.join('\n'));
      console.error(`Removed legacy claude-mem alias from ${filePath}`);
    } catch (error: unknown) {
      console.warn(`[uninstall] Could not rewrite ${filePath}:`, error instanceof Error ? error.message : String(error));
    }
  }
}

export function removeFromClaudeSettings(): void {
  const settings = readJsonSafe<Record<string, any>>(claudeSettingsPath(), {});
  let dirty = false;

  if (settings.enabledPlugins?.['claude-mem@thedotmack'] !== undefined) {
    delete settings.enabledPlugins['claude-mem@thedotmack'];
    dirty = true;
  }

  // Symmetric counterpart to disableClaudeAutoMemory() in install.ts. The
  // installer sets env.CLAUDE_CODE_DISABLE_AUTO_MEMORY = "1" to suppress
  // Claude Code's built-in auto-memory; on uninstall we restore the host
  // CLI's default behavior by removing that key. The value-equality guard
  // (=== '1') ensures we only strip the specific token the installer wrote

View on GitHub (pinned to d8bc9755e7)