anthropics / anthropics/claude-code

[BUG] Sidebar groups render based on stale 'order' key, not groups[] or member count — root cause + schema for #79810/#58193/#79156

Open
#93,210 0 comments 0 reactions 0 assignees View on GitHub
area:desktop bug has repro platform:macos
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

### Preflight Checklist

- [x] I have searched existing issues and this hasn't been reported with this level of detail (related: #79810, #58193, #79156, #65669 — all describe the symptom, none identify the actual data/rendering mechanism)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code

### What's Wrong?

Custom sidebar groups (Desktop app, "Group by: Custom groups") intermittently fail to render even though their definitions are fully intact — confirmed by directly parsing the underlying LevelDB store rather than guessing from symptoms.

**Where the data actually lives:** `~/Library/Application Support/Claude/Local Storage/leveldb/`, key `_https://claude.ai\0dframe-store` — a Zustand-persisted JSON blob (localStorage, not IndexedDB). Relevant shape:

```json
{
"state": {
"customGroupsByScope": {
"/": {
"groups": [
{ "id": "cg-...", "name": "SomeGroup" }
],
"assignments": { "code:local_": "cg-..." },
"order": { "cg-...": ["code:local_", ...] }
}
},
"pendingLegacyGroupMigration": null
}
}
```

**Root cause of the "some groups render, some don't" symptom (verified from live data, two real groups from the same account/scope, same moment in time):**

Rendering is **not** based on current member count. It's based on whether the group has *any* key present in `order` at all:

- Group A had `"order": { "cg-XXXX": [] }` — an **empty array**, but the key exists. Result: renders in the sidebar as an empty "Drag or move sessions here" dropzone.
- Group B (and 8 others in the same scope) had **no key at all** in `order` for their group id, despite existing in `groups[]` and therefore still appearing in the "Move to group" context-menu list. Result: does not render in the sidebar at all, even though it's a fully valid, selectable group.

So a group that has *never* had a session explicitly filed into it via this UI (no `order` key ever created) is invisible in the sidebar, while a group that once had a session and lost it (empty array, but key retained) stays visible. `groups[]` (the definition list) and `order`/`assignments` (the render/membership state) are inconsistently read by different parts of the UI — the "Move to group" menu reads `groups[]` only, the sidebar list apparently requires an `order` entry.

**Second finding — likely explains reports of groups losing all their old members ("permanently deleted", per #58193):**

The oldest available local snapshot (earliest-dated file in the whole Local Storage store) already shows `"assignments": {}` and `"order": {}` for **every** group that existed at that point — not low, zero. The same JSON has a field named `pendingLegacyGroupMigration`, currently `null`. This strongly suggests there is (or was) a migration path meant to carry an older, pre-"custom groups" organization scheme (most likely the working-directory/git-root-derived auto-grouping described in #79156) into this new named-group + assignments/order schema — and for at least this account, it migrated the group *names* but not any historical *membership*, leaving `assignments`/`order` empty from day one for groups that the user remembers having had content.

### What Should Happen?

1. Sidebar rendering should be based on `groups[]` (show every defined group, consistently, regardless of current member count) — OR at minimum, "Move to group" and the sidebar list should agree on the same membership source. Right now they don't.
2. If `pendingLegacyGroupMigration` is a real migration flag, it should either actually carry old membership over, or the field/mechanism should be removed if it's dead code — right now it silently no-ops while implying migration happened.
3. Losing group membership should not be effectively unrecoverable client-side. At minimum, expose `order`/`assignments` state (or a "which sessions used to be here" hint) rather than only being reconstructable by parsing LevelDB directly.

### Error Messages/Logs

No errors surfaced anywhere (UI, Console.app, or Claude Code debug logs) — this is a silent read/render inconsistency, not a crash.

### Steps to Reproduce

1. Have a Desktop app account with several custom groups, some of which have never had a session dragged into them since the "custom groups" feature was introduced (only defined via `groups[]`, no `order` entry).
2. Switch `Group by` to `Custom groups`.
3. Observe: groups with an `order` entry (even `[]`) render; groups with none don't, despite both being valid, selectable entries in "Move to group".
4. To reproduce the "old members gone" symptom: pick a group that currently has zero entries in `assignments`/`order`, use "Move to group" to file a session into it. Observe the group reappears in the sidebar with exactly the one just-added session — no trace of any session that may have been associated with that group name previously.

### Claude Model

N/A — this is a Desktop app client-storage/rendering bug, unrelated to model choice.

### Is this a regression?

Unknown — but `pendingLegacyGroupMigration` being `null` from the earliest available local snapshot suggests this may be present since the "custom groups" feature's introduction, not a recent regression.

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce with Desktop app custom groups and inspect the persisted blob at ~/Library/Application Support/Claude/Local Storage/leveldb/ key _https://claude.ai\0dframe-store. Trace the UI paths that read groups[], order, assignments, and pendingLegacyGroupMigration. Done means the sidebar and Move to group menu use consistent group state, with migration behavior clarified or fixed.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, json, macos
Domain
data, desktop, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.