[BUG] VS Code: a session picked from History in a new tab opens in the sidebar instead, if the sidebar has had it open

Status Open
Reported on v2.1.296
Maintainer reply None cached
Activity 0 comments · opened Oct 13, 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?

With claudeCode.preferredLocation set to panel, and a session open in the secondary (right) sidebar, I open a new editor tab (Cmd+Shift+Esc), click Session history in that tab, and choose a past session. It doesn't open in the new tab. The right sidebar switches to it, so the conversation I was working in there leaves the screen, and the new tab stays empty.

This happens to any session the sidebar has shown earlier in the window, and it also breaks the workaround in #93199 (open a new tab before choosing from History). Additional Information traces the cause.

What Should Happen?

A session chosen from History in an editor tab should open in that tab, and the sidebar should let go of it if it isn't showing it. If it has to stay in the sidebar, for example because a turn is running there, the extension should say so rather than switch the sidebar without warning.

Error Messages/Logs

None shown.

Steps to Reproduce

I saw the symptom in normal use. These steps are reconstructed from the code path in Additional Information, and I haven't run them as written.

  1. Set claudeCode.preferredLocation to panel.
  2. In the right sidebar, open session A from Session history. A must be a real session with messages, not a blank chat.
  3. In the same sidebar, open session B from Session history.
  4. Press Cmd+Shift+Esc to open a new Claude editor tab.
  5. In that tab, click Session history and choose session A.
  6. The sidebar switches from B to A, and the new tab stays empty.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.296 (VS Code extension), VS Code 1.141.0

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other (the VS Code extension's own panel)

Additional Information

Technical analysis. This comes from reading the bundled extension.js and webview/index.js in 2.1.296. The bundle is minified, so I name class methods and message types, which keep their names. Minified function names differ between builds.

The picker's choice goes through the path that focuses a tab already showing the session (added in 2.1.260, per #93199). That path counts every session the sidebar has a Claude process on as already open, including sessions the sidebar isn't showing.

  1. The picker, in the tab's webview. Choosing a session calls focusTabShowing(session, { includeSidebarChat: true }). With includeSidebarChat, tabOpenElsewhere() checks keysShownElsewhere(), which is openSessionIds (sessions in editor tabs) plus sidebarSessionIds. A is in sidebarSessionIds, so the picker doesn't load A into the current tab. It calls openInEditor(A), which sends an open_in_editor request.
  2. The extension host. open_in_editor runs claude-vscode.editor.open with A, fullEditor = true and programmatic: "honor-preferred-location". Because preferredLocation is panel, the target is panel, so it calls createPanel(A, …).
  3. createPanel. No editor tab has A (sessionPanels), so it checks sidebarHoldsSession(A). That returns true, so createPanel returns showSessionInSidebar(A), which calls activateInSidebar(A) and reveals the sidebar view. The sidebar webview makes A its active session, B leaves the screen, and the tab stays empty.
  4. Why the sidebar holds A. sidebarHoldsSession is true if the session is the one the sidebar shows, or if the sidebar has a channel on it (hasChannelOnSession, which counts pending channels too). sidebarSessionIds is built the same way, from sessionIdsWithChannels() plus the shown session. When a surface's active session changes, the webview calls endUnusedProcess() on the others, and that ends only blank chats. isUnusedBlankChat() requires no transcript on disk, no title and no prompt or reply. So a real session keeps its Claude process, and its channel, until the sidebar webview is torn down. Every real session opened in the sidebar during the window's life keeps routing back to the sidebar.

createPanel makes the same check on every other route to a session:

  • vscode://anthropic.claude-code/open?session=…, which runs claude-vscode.primaryEditor.open
  • session list rows, through open_in_editor
  • new_conversation_tab requests that carry a session ID

Possible fix. Send a session to the sidebar only when the sidebar is showing it (shownSessionId). If the sidebar has it only as a background channel, end that process, as endUnusedProcess() does for blank chats, and open the session in the tab. If a turn is running in that background session and it can't move, say so rather than switch the sidebar.

View original on GitHub ↗