Skip to content

Windows: session_start hook dies with UnicodeEncodeError ('charmap' can't encode U+27E6 ⟦) — entire SessionStart memory injection lost #96

Description

@mbe14

Environment: Windows 11 Pro (build 26200), Python 3.13.13, cortex plugin 4.13.0 installed through the marketplace, Western locale (ANSI code page 1252). Same box as #91#95.

Symptom

Every Claude Code session start shows:

SessionStart:startup hook error
Failed with non-blocking status code: [cortex-launcher] Failed to run mcp_server.hooks.session_start: 'charmap' codec can't encode character '⟦' in position 25: character maps to <undefined>

and — the actual damage — no memory context is injected at all. The whole SessionStart banner (anchors, hot memories, checkpoint, grooming line) is silently lost on Windows.

Root cause

The generic wrapper at scripts/launcher.py:320 is just reporting an exception raised inside the hook. The real crash site is print(context) in mcp_server/hooks/session_start.py (~line 1089).

The banner header is:

## Cortex Memory Context ⟦rcpt:N⟧

"## Cortex Memory Context " is exactly 25 characters, so position 25 is U+27E6 — the injection-receipt marker. The hook's stdout is a pipe (Claude Code's hook runner), so CPython encodes it with the locale/ANSI code page (charmap → cp1252) unless PYTHONUTF8/PYTHONIOENCODING is set, and cp1252 has no .

The receipt marker makes the crash deterministic on every start, but any non-cp1252 character in injected memory content (→, ✅, non-Latin scripts…) triggers the same failure — and auto_recall emits ⟦rcpt:…⟧ markers too, so the UserPromptSubmit injection path is exposed the same way.

Repro (A/B)

# stdout is a pipe, like under the hook runner
echo '{"session_id":"t","cwd":"C:\\src\\myproject"}' | \
  python3 scripts/launcher.py mcp_server.hooks.session_start > out.txt 2>&1
echo $?   # 1; out.txt ends with the charmap UnicodeEncodeError

echo '{"session_id":"t","cwd":"C:\\src\\myproject"}' | \
  PYTHONUTF8=1 python3 scripts/launcher.py mcp_server.hooks.session_start > out.txt 2>&1
echo $?   # 0; out.txt contains the full banner: "## Cortex Memory Context ⟦rcpt:18⟧ …"

Suggested fix

One choke point covers the server and every hook — at the top of main() in scripts/launcher.py:

for stream in (sys.stdout, sys.stderr):
    try:
        stream.reconfigure(encoding="utf-8", errors="replace")
    except Exception:
        pass

Claude Code consumes hook stdout as UTF-8, so the ⟦rcpt:N⟧ markers round-trip fine once they can actually be encoded (verified with the PYTHONUTF8=1 run above — the injected banner renders correctly).

Workaround

"env": { "PYTHONUTF8": "1" } in Claude Code's settings.json — works, but every Windows user hits this out of the box until the launcher sets the encoding itself.

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