anthropics / anthropics/claude-code

VS Code extension: clicking chat links to binary files (images) silently fails — unhandled showTextDocument rejection

Open
#81,227 3 comments 8 reactions 0 assignees View on GitHub
area:ide
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## Summary

In the VS Code extension's chat panel, clicking a markdown link to any **binary file (PNG, JPG, PDF, …) silently does nothing**. The extension resolves the path correctly, then tries to open it with `vscode.window.showTextDocument()`, which rejects binary files — and the rejection is unhandled, so the user gets no error, no feedback, nothing.

For image-heavy workflows (e.g. Claude generating/reviewing art assets and linking them for review) this makes every link the model emits dead, and the user has to copy paths by hand and navigate manually.

## Environment

- Claude Code VS Code extension: reproduced on every version I inspected from **2.1.123 (April) through 2.1.220 (current)** — the code path is unchanged
- IDE: Antigravity (VS Code fork), macOS 15 / Darwin 25.5.0 — but the bug is in the extension's own handler and should reproduce in stock VS Code (`showTextDocument` rejects binaries everywhere)

## Repro

1. Have Claude output a relative markdown link to any PNG in the workspace, e.g. `[shot.png](assets/shot.png)`
2. Click it in the chat panel
3. Nothing happens. The extension host log shows:

```
[error] CodeExpectedError: cannot open file:///Users/me/project/assets/shot.png.
Detail: File seems to be binary and cannot be opened as text
```

Links to text files (`.md`, `.ts`, …) work fine.

## Root cause

In `extension.js`, the webview's `open_file` request is handled by `openFile(filePath, location)`, which — after correct path resolution and a directory check that goes to `revealInExplorer` — unconditionally does:

```js
ue.window.showTextDocument(n).then((i) => { /* selection/reveal logic */ })
```

- `showTextDocument` rejects with `CodeExpectedError` for binary files
- the promise has no rejection handler, so the failure is swallowed silently

No link-format workaround exists from the model side: `file://` hrefs survive the markdown sanitizer but the webview host drops them, and custom-scheme deep links (`vscode://file/...` / fork equivalents) are stripped by the sanitizer's `allowedSchemes` list.

## Suggested fix

Route non-text files through the generic opener, e.g.:

```js
vscode.commands.executeCommand('vscode.open', uri)
```

either by sniffing known binary extensions before `showTextDocument`, or as a `.catch()` fallback when `showTextDocument` rejects (which also future-proofs any other non-text-openable resource). `vscode.open` shows images in the built-in image preview, which is presumably the expected UX.

At minimum, surfacing the rejection as an error notification would stop the failure from being silent.

## Current workaround

Locally patching the installed `extension.js` to insert the extension-sniff + `vscode.open` fallback before the `showTextDocument` call fixes clicking for images — but the patch is wiped by every extension auto-update (which currently ship every 1–2 days), hence this report.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in extension.js at the webview open_file handler and trace openFile(filePath, location) through the showTextDocument call. Verify the behavior with a markdown link to a text file and a binary file such as a PNG, then implement the generic opener or rejection handling described in the issue. Done means binary links open or provide an error while text-file links retain their current selection behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, vscode
Domain
desktop, devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.