[BUG] VS Code extension 2.1.202: session delete (trash) is a no-op for state-derived rows — identity-based optimistic removal never matches, hiddenSessionIds never applied to the rendered list

Status Open
Reported on v2.1.202
Maintainer reply None cached
Activity 1 comment · opened Jul 20, 2026

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?

Clicking the trash ("Delete session") on a session row in the VS Code extension's session list reorders the list and moves focus, but the row never disappears. Clicking repeatedly re-sends the same delete. After a window restart the list resets wholesale, which makes the delete look like it eventually worked — it didn't.

We instrumented this end to end (semantic click capture, state.vscdb snapshots before/after each click, DOM session recording) and traced it to three cooperating defects, all verifiable in the shipped bundle (anthropic.claude-code 2.1.202, darwin-arm64; same shapes present since at least 2.1.200):

  1. Optimistic removal compares by object identity (webview/index.js):

this.sessions.value=this.sessions.value.filter((i)=>i!==e)
Rows the webview rebuilds from session state via fromStateInfo(...) are new object instances every render, so the filter never matches and removes nothing. Only rows whose object identity is stable in sessions.value (created in-window into the store) can disappear live.

  1. The delete request itself always fires and persists a soft-hide: the webview sends {type:"delete_session", sessionId}; the extension host handler is

deleteSession(e){return await this.settings.hideSession(e)
globalState.update("hiddenSessionIds", ...).
We observe exactly one id appended per session in state.vscdb (deduped on re-click).

  1. The rendered list never consults hiddenSessionIds for state-derived rows: sessions whose ids are verifiably present in the hidden list continue to display for as long as they exist in session state. The new Set(this.settings.getHiddenSessionIds()) filter only affects the local transcript listing.

Net effect: for state-derived rows, "delete" writes a tombstone nothing reads and removes nothing on screen. The user cannot delete these sessions at all.

Context: we drive sessions through a custom claudeCode.claudeProcessWrapper integration, which makes state-derived rows the dominant row kind in our list — but the defective code paths above are generic and not specific to our wrapper.

What Should Happen?

Clicking the trash on any session row — regardless of whether the row came from the local transcript store or was rebuilt from session state — should remove the row from the visible list immediately, and the session should stay gone across window reloads.

Suggested fix (two small changes):

  • Compare by session id in the optimistic removal (e.g. filter(i => i.sessionId.value !== e.sessionId.value)), and
  • apply the hiddenSessionIds filter uniformly to every row source (local transcript rows and state-derived rows), or re-emit the filtered list after the host acks delete_session.

Error Messages/Logs

No error is surfaced anywhere — the failure is silent. Observable evidence instead:

# Before a click on a fresh session's trash:
sqlite3 ".../User/globalStorage/state.vscdb" \
  "SELECT json_extract(value,'$.hiddenSessionIds') FROM ItemTable WHERE key='Anthropic.claude-code';"
# -> 7 ids
# After the click (row still visible in the list):
# -> 8 ids (new session's uuid appended)
# Re-clicking the same row any number of times: count unchanged (dedup), row still visible.

Steps to Reproduce

  1. Use the VS Code extension in any setup where the session list shows state-derived rows (rows rebuilt from session state rather than local transcripts — e.g. sessions driven through a claudeCode.claudeProcessWrapper integration; the identity-filter defect is visible in the bundle regardless of setup).
  2. Create a session (type any prompt) so a row appears in the session list.
  3. Hover the row and click the trash ("Delete session").
  4. Observe: the list may reorder and focus jumps, but the row remains. Repeat clicks change nothing visible.
  5. Inspect <user-data-dir>/User/globalStorage/state.vscdbItemTable key Anthropic.claude-codehiddenSessionIds: the session's id IS appended on the first click (the delete pipeline runs; only the UI never reflects it).
  6. Reload the window: the list rebuilds from state; hidden ids are still not applied.

Code-level confirmation (no repro needed): in the shipped webview/index.js of 2.1.202, find this.sessions.value=this.sessions.value.filter((i)=>i!==e) (identity compare) and fromStateInfo( (per-render row rebuild) — together these make live removal impossible for state-derived rows; in extension.js, deleteSession(e){return await this.settings.hideSession(e) shows delete is a pure soft-hide whose result the state-derived listing never reads.

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.215 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗