thedotmack/claude-mem · warning

[ide-detection] Failed to read VS Code extensions directory:

Error message

[ide-detection] Failed to read VS Code extensions directory:

What it means

hasVscodeExtension() reads ~/.vscode/extensions and logs this warning if readdirSync throws, returning false so IDE detection degrades gracefully. It means the extensions directory exists but could not be read — detection of the VS Code extension is skipped.

Solutions

  1. Inspect `ls -la ~/.vscode/extensions` — fix it if it is a file or broken symlink.
  2. Correct directory permissions so the current user can read it.
  3. Exclude the directory from security software interference.
  4. Re-run IDE detection after repair; a false return only skips VS Code extension hints, other IDE detection continues.

Example fix

// before
if (!existsSync(extensionsDirectory)) return false;
// after (stat + isDirectory check avoids the exists-but-not-a-dir trap)
try {
  if (!statSync(extensionsDirectory).isDirectory()) return false;
} catch { return false; }
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from 'fs';
function isReadableDirectory(p: string): boolean {
  try { return statSync(p).isDirectory(); } catch { return false; }
}
// before readdir: if (!isReadableDirectory(extensionsDirectory)) return false;

Type guard

function hasFsError(e: unknown): e is NodeJS.ErrnoException {
  return e instanceof Error && 'code' in e;
}

Try / catch

try {
  const entries = readdirSync(extensionsDirectory);
  return entries.some(e => e.toLowerCase().includes(fragment.toLowerCase()));
} catch (error: unknown) {
  console.warn('[ide-detection] Failed to read VS Code extensions directory:', error instanceof Error ? error.message : String(error));
  return false;
}

Prevention

When it happens

Trigger: readdirSync(extensionsDirectory) throws despite existsSync passing — e.g. the path exists but is a file, or permission/bit-flip issues between the existence check and the read (TOCTOU), or an I/O error.

Common situations: ~/.vscode/extensions is a broken symlink or plain file; permissions tightened by security software; directory removed between check and read; disk I/O errors; synced/roamed profiles with restricted ACLs.

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.

Related errors


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

Appendix: source

Thrown at src/npx-cli/commands/ide-detection.ts:40

      execFileSync('which', [command], { stdio: 'ignore' });
    }
    return true;
  } catch (error: unknown) {
    if (process.env.DEBUG) {
      console.error(`[ide-detection] ${command} not in PATH:`, error instanceof Error ? error.message : String(error));
    }
    return false;
  }
}

function hasVscodeExtension(extensionNameFragment: string): boolean {
  const extensionsDirectory = join(homedir(), '.vscode', 'extensions');
  if (!existsSync(extensionsDirectory)) return false;
  try {
    const entries = readdirSync(extensionsDirectory);
    return entries.some((entry) => entry.toLowerCase().includes(extensionNameFragment.toLowerCase()));
  } catch (error: unknown) {
    console.warn('[ide-detection] Failed to read VS Code extensions directory:', error instanceof Error ? error.message : String(error));
    return false;
  }
}

export function detectInstalledIDEs(): IDEInfo[] {
  const home = homedir();

  return [
    {
      id: 'claude-code',
      label: 'Claude Code',
      detected: isCommandInPath('claude'),
      hint: 'recommended',
    },
    {
      id: 'opencode',
      label: 'OpenCode',
      detected:

View on GitHub (pinned to d8bc9755e7)