[DOCS] Auto memory: the `MEMORY.md` load limit is 25,000 UTF-16 code units, not 25KB

Status Open
Reported on v2.1.281
Maintainer reply None cached
Activity 0 comments · opened Sep 26, 2026

Documentation Type

Incorrect/outdated documentation

Documentation Location

https://code.claude.com/docs/en/memory

Section/Topic

Auto memory, How it works, and the comparison table's Loaded into row

Current Documentation

As read on 26 September 2026, the How it works paragraph gives the limit as "the first 200 lines of MEMORY.md, or the first 25KB, whichever comes first". The table's Loaded into row gives the same figure, and the next paragraph says Claude Code measures the file against the 200-line and 25KB limits after each write.

What's Wrong or Missing?

The size limit is 25,000 UTF-16 code units, which is JavaScript's string length, and the cut falls at the end of a whole line. It isn't 25KB, as either 25,000 or 25,600 bytes, and it isn't 25,000 characters either, because an emoji outside the Basic Multilingual Plane counts as two.

I measured it on Claude Code 2.1.281 (macOS, the binary bundled with the Claude desktop app) with a synthetic index. It has 180 lines, so the 200-line limit can't interfere, and every line is the same: a label (L001 to L180), ten 😀, thirty é, x padding, and end L001 and so on. Each line is 160 code points, 170 UTF-16 units and 220 UTF-8 bytes. That makes each candidate rule predict a different last line:

| rule | last whole line |
|---|---|
| 25,000 code points | L156 |
| 25,600 code points | L160 |
| 25,000 UTF-16 units | L147 |
| 25,600 UTF-16 units | L150 |
| 25,000 bytes | L113 |
| 25,600 bytes (25 KiB) | L116 |

Two fresh sessions each saw exactly through L147. Both ran claude -p --model claude-haiku-4-5 --tools "" --no-session-persistence --settings '{"autoMemoryDirectory": "<test folder>"}', with a prompt asking for the last labeled line in context. The loader's own notice agreed:

WARNING: MEMORY.md is 29.9KB (limit: 24.4KB) — index entries are too long. Only part of it was loaded: 33 of 180 lines were cut off, starting at line 148

The notice reports UTF-16 units divided by 1,024 as "KB": 30,600 ÷ 1,024 = 29.9, and 25,000 ÷ 1,024 = 24.4. So the docs say 25KB, the notice says 24.4KB, and the loader cuts at 25,000 UTF-16 units.

A second index rules out line length. It had 100 lines of 300 code points each (320 UTF-16 units, 420 bytes), past the "~200 chars" the notice recommends. Two more sessions cut at L078, as 25,000 UTF-16 units predicts; 25,000 code points would give L083, and 25,000 bytes L059. The notice said "MEMORY.md is 31.2KB (limit: 24.4KB)", which is 32,000 ÷ 1,024.

For plain ASCII text, bytes, code points and UTF-16 units are the same count, so reading "25KB" as 25,000 bytes happens to be right, though the notice's "24.4KB" still disagrees with the docs' "25KB". The counts drift apart with accented letters, symbols and emoji, and anyone budgeting with wc -c, or reading "25KB" as bytes, then gets a different number from the one the loader uses.

The notice also says "index entries are too long" in both tests, including the first, where every entry was 160 characters, under the "~200 chars" it recommends. The cut depends on the file's total size, not on the length of any entry.

The generator, for anyone who wants to reproduce it:

lines = []
for n in range(1, 181):
    head, tail = f"- L{n:03d}: ", f" end L{n:03d}"
    body = ("é" * 3 + "\U0001F600") * 10
    lines.append(head + body + "x" * (159 - len(head) - len(body) - len(tail)) + tail + "\n")
open("MEMORY.md", "w", encoding="utf-8").write("".join(lines))

Suggested Improvement

The first 200 lines of MEMORY.md, or the first 25,000 characters, whichever comes first, are loaded at the start of every conversation. Characters are counted as UTF-16 code units, so an emoji outside the Basic Multilingual Plane counts as two. The cut falls at the end of the last whole line within both limits.

The Loaded into row would read "first 200 lines or 25,000 characters". The notice would be clearer in the same unit as the docs, rather than "KB" calculated from UTF-16 units, and naming the file's total size as the cause rather than entry length.

Impact

Low - Minor confusion or inconvenience

Additional Context

Related, not duplicates: #79217, #77647, #25006, #40210.

An earlier observation, on Claude Code 2.1.260: the after-write reminder the docs describe gave the same figure, "approaching the 24.4KB read limit".

---

🤖 Investigated with Claude Code (Claude Opus 5.5), which designed and ran the tests above and drafted this report with me.

View original on GitHub ↗