[BUG] VS Code extension: chat file links are never wired to the existing open_file bridge

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

Preflight Checklist

  • [x] I have searched existing issues — this behaviour has been reported before (#10846, #16056, #44713, #51015, #57100, #72889), but every one of those is closed and locked, and none of them identifies the cause. The closing bot asks to file a new issue, so here it is, with the root cause.
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

Markdown file links rendered in the chat panel of the VS Code extension are styled as links but clicking them does nothing — no open, no reveal, no error. This is an affordance mismatch, and it hits exactly at handoff time, when Claude has just produced a deliverable.

The extension's own system prompt (## Code References in Text) instructs Claude to emit file references in precisely this markdown format. The links are dead on arrival.

I dug into the installed bundle. There are two independent defects, and neither is "link handling is missing".

1 — the anchors are never wired to the bridge that already exists.

The open path is present, complete, and in active use by the file chips and the diff view:

webview/index.js   openFile(filePath, location)
                     -> sendRequest({type: "request", requestId, request: {type: "open_file", filePath, location}})
extension.js       case "open_file": -> this.openFile(request.filePath, request.location)

The host side is thorough: it resolves relative paths against cwd, has fallbacks when the file is missing, and calls revealInExplorer for directories. Nothing about it is broken. The rendered <a> elements simply never call it.

2 — binary files fail silently even once (1) is fixed.

The host's openFile ends in

vscode.window.showTextDocument(uri).then(cb)     // no rejection handler

showTextDocument rejects for non-text files. With no onRejected and no .catch, the rejection is unhandled and the user sees nothing at all. So a link to a .png or .pdf stays dead even after the anchors are wired up.

What Should Happen?

Clicking a file link should open the file — text in the editor, binary in its own viewer (image preview, PDF) — and a directory should reveal in the Explorer. Line anchors (file.md#L42, #L42-L51) should map to the location argument the host already accepts.

Error Messages/Logs

None. The click is a silent no-op. Defect 2 produces an unhandled promise rejection from showTextDocument inside the extension host; nothing surfaces to the user.

Steps to Reproduce

  1. Ask Claude to create two files in a subfolder, e.g. docs/note.md and docs/chart.png.
  2. Claude replies with [note.md](docs/note.md) and [chart.png](docs/chart.png) — the format its system prompt mandates.
  3. Click either link in the chat panel. Nothing happens.
  4. Same result with absolute paths, file:/// URLs and directory paths (previously reported in #51015).

Claude Model

Opus 5

Is this a regression?

Yes, and a recurring one. #10846 was reported fixed in v2.1.4; broken again by v2.1.92 (#44713); again in 2.1.132 (#57100); still broken in 2.1.263.

Last Working Version

2.1.4 (per #10846)

Claude Code Version

Extension anthropic.claude-code-2.1.263-linux-x64, VS Code 1.132.0

Platform

VS Code extension (chat panel webview)

Operating System

Debian 13 (trixie), KDE Plasma on X11

Terminal/Shell

zsh — not relevant here; the defect is in the webview panel, not the CLI.

Additional Information

The desktop side is not at fault. Verified locally before filing: VS Code installed from the native .deb (no Flatpak/Snap sandbox), xdg-open present, three xdg-desktop-portal processes running, an image handler registered for image/png. None of that is ever reached.

Suggested fix — both parts are small:

  • Webview: on click of an anchor whose href carries no URL scheme and is not a # fragment, parse an optional #L<n> / #L<n>-L<m> suffix into location and call the existing openFile(). External schemes keep their current behaviour.
  • Host: give showTextDocument(uri).then(cb) a rejection handler that falls back to vscode.commands.executeCommand("vscode.open", uri). One argument.

Workaround while this is open: a patch script that applies both fixes to the locally installed extension — idempotent, backs up per version, verifies with node --check and rolls back automatically on a syntax error, --revert to undo. It contains no Anthropic code; it locates the insertion points by pattern. → https://github.com/0nelight/claude-code-vscode-linkfix

Happy to open a PR against the extension source if that is ever practical.

View original on GitHub ↗