[BUG] `/branch` writes every message twice, creating a branch session ~1.5x larger than parent
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
/branch creates a branch session file that is significantly larger than the parent session. In my case: parent = 8,892 lines (33 MB), branch = 12,056 lines (42 MB).
Investigation shows the branch function writes two copies of every message to the output file — one with a forkedFrom field (the intended forked entry) and one without (an unintended duplicate). This results in 4,205 UUIDs appearing exactly twice in the branch JSONL.
Breakdown of the branch file (12,056 entries):
- 7,828 entries WITH
forkedFrom— the intended forked messages - 4,228 entries WITHOUT
forkedFrom— unintended duplicates - 4,205 UUIDs appear exactly 2 times
- All 12,056 entries have the branch's sessionId (not the parent's)
What Should Happen?
The branch should contain each message exactly once. The branch file should be approximately the same size as the parent session at the time of branching.
Error Messages/Logs
# No error — /branch succeeds silently but produces an oversized file.
$ wc -l parent-session.jsonl
8892 # parent at time of investigation (was ~8,378 at branch time)
$ wc -l branch-session.jsonl
12056 # branch — 44% more lines than the parent had
# UUID duplication check:
# Total unique UUIDs in branch: 7,836
# UUIDs appearing exactly 2 times: 4,205
Steps to Reproduce
- Work in a Claude Code session until it has meaningful conversation history
- Run
/branch <name> - Compare line counts:
wc -l ~/.claude/projects/<project>/*.jsonl - Check for duplicate UUIDs in the branch file:
import json
from collections import Counter
uuids = Counter()
with open('branch-session.jsonl') as f:
for line in f:
d = json.loads(line)
uuid = d.get('uuid')
if uuid:
uuids[uuid] += 1
dupes = sum(1 for v in uuids.values() if v > 1)
print(f"UUIDs appearing >1 time: {dupes}")
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.86
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Windows Terminal
Additional Information
Root Cause (from deobfuscated source)
The branch function (minified as Yf9 in v2.1.86) builds two arrays in one loop:
let D = null, w = [], M = [];
for (let j of Y) {
let X = {...j, sessionId: $, parentUuid: D, isSidechain: false,
forkedFrom: {sessionId: q, messageUuid: j.uuid}}; // WITH forkedFrom
let J = {...j, sessionId: $}; // WITHOUT forkedFrom
M.push(J); // pushed to M (returned as serializedMessages)
w.push(gH(X)); // pushed to w (written to file)
if (j.type !== "progress") D = j.uuid;
}
// writes w to the branch JSONL file
await TSH.writeFile(_, w.join('\n') + '\n', ...);
// returns M as serializedMessages
return {sessionId: $, ..., serializedMessages: M, ...};
The caller then does $.resume(forkPath, serializedMessages, "fork"), which loads the M array into the runtime. The runtime re-persists the pre-compact portion of these messages back to the same branch JSONL — resulting in those messages appearing twice: once from w (with forkedFrom) and once from the resume replay (without forkedFrom).
Evidence confirms an exact split at the compact boundary:
- Messages before compact point (line 0–4,204): ALL duplicated (4,205 UUIDs × 2)
- Messages after compact point (line 4,205+): ALL single (3,631 UUIDs × 1)
- Every duplicated UUID has exactly one entry with
forkedFromand one without — zero exceptions
Suggested fix
The resume(path, serializedMessages, "fork") call should not re-persist messages that are already written to the branch file by the branch function. Either:
- Skip writing
serializedMessagesto the JSONL during fork-mode resume (they're already inw) - Or deduplicate on write — if a UUID already exists in the file, don't append it again
The root cause was identified by extracting strings from the compiled binary at ~/.local/share/claude/versions/2.1.86 and cross-referencing with the JSONL structure of the branch file. The forkedFrom field presence/absence and the exact split at the compact boundary were the key evidence.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗