Skip to content

Windows: settings.json written with UTF-8 BOM causes JSON parse failure on every hook #3013

Description

@kellyfriend

Bug Description

On Windows with PowerShell 5.1, settings.json is written with a UTF-8 BOM (EF BB BF). Node.js's JSON parser treats the BOM byte as an unrecognized token, causing the worker to fail loading its config on every startup.

Error Message

[LOGGER] Failed to load log level from settings: JSON Parse error: Unrecognized token ''
claude-mem worker unreachable for N consecutive hooks.

The empty string in Unrecognized token '' is the invisible BOM character ().

Root Cause

PowerShell 5.1 (Windows PowerShell, not PowerShell Core) defaults to UTF-8 with BOM for certain write operations. When settings.json is written by PowerShell-based tooling, the BOM is prepended.

Confirmed via:

$bytes = [System.IO.File]::ReadAllBytes("$env:USERPROFILE\.claude-mem\settings.json")
# Result: first 3 bytes = 0xEF 0xBB 0xBF  (UTF-8 BOM)
# File content is structurally valid JSON — BOM prefix breaks the parser

Impact

  • Worker fails to start on every Claude Code session restart
  • Each hook call waits for timeout before failing → massive latency penalty on all tool calls (Glob, Read, Grep, Agent, etc.)
  • After 24 consecutive failures, CAPTURE_BROKEN flag is set and worker is permanently disabled until manual reset
  • Only workaround: manually change port + reset hook-failures.json + delete CAPTURE_BROKEN
  • Long-running Agent tasks accumulate the full timeout overhead on every single tool call

Suggested Fixes

Option 1 — strip BOM on read (minimal change):

const raw = fs.readFileSync(settingsPath, 'utf8').replace(/^/, '');
const settings = JSON.parse(raw);

Option 2 — enforce utf8 without BOM on write (preferred):

fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), { encoding: 'utf8' });
// Node.js fs.writeFileSync with 'utf8' never writes a BOM

Option 3 — self-healing recovery (bonus):
Instead of setting CAPTURE_BROKEN permanently after N failures, auto-reset consecutiveFailures so the worker retries on next session start.

Environment

  • OS: Windows 11 Pro 10.0.26200
  • Shell: PowerShell 5.1 (Windows PowerShell)
  • Node.js: invoked via bun-runner.jsworker-service.cjs
  • Claude Code: latest

Related

On Windows, TCP sockets enter TIME_WAIT state (default 240s) after the worker process exits abnormally. This compounds the BOM issue: even if the JSON bug were fixed, the port remains unavailable for ~4 minutes after a crash. Workaround: set TcpTimedWaitDelay=30 in the Windows registry to reduce TIME_WAIT to 30s.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions