P0: recalled-memory truncation splits UTF-8 characters, poisoning the request body (both wires, ships today) #123
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Affects every shipped build today, including Tim's own running Neuron. Fix is written and under review in PR #122 but reaches no one until that merges and a brain is rebuilt.
Symptom
Chat fails with
{"error":"llm unavailable"}and no explanation. Intermittent-looking; actually deterministic per conversation.Root cause
The session preload cuts recalled memory content at fixed byte lengths — the continuity snippet (
str_slice(acc, 0, 350)) andsession_preload_bullets' per-bullet cut.str_slice/str_lencount bytes, so a cut landing inside a multi-byte UTF-8 character leaves a dangling lead byte in the system prompt, making the entire request body invalid UTF-8. Providers reject it outright.Evidence (captured body, not inferred)
18,710 bytes; decode fails at offset 18,248 on
0xe2:A run of box-drawing rules (U+2500 =
E2 94 80) sliced mid-character, sourced from a stored memory containing table borders.Why it matters more than it looks
Fix (in PR #122)
utf8_safe_slice(s, n)— walks back over UTF-8 continuation bytes to the lead byte and keeps the character only if all its bytes survived — applied at both cut sites. Covered bytests/test_utf8_slice.el(18/18: 2-, 3- and 4-byte characters, boundary-exact keeps, the real box-rule shape), which also pins the runtime semantics the fix depends on (str_lencounts bytes;str_char_codereturns the byte value) so a future runtime change fails loudly instead of silently rotting.🤖 Generated with Claude Code