VS Code extension: file links in responses do not open when the path contains non-ASCII characters
Summary
In the VS Code extension, clicking a file link in an assistant response does nothing when the path contains non-ASCII characters. ASCII-only paths open correctly.
My workspace uses Japanese filenames almost everywhere, so in practice no file link in a response has ever been clickable. There is no error and nothing in the output channel, so it just looks like the links are decorative.
Environment
- Claude Code for VS Code: v2.1.220 (win32-x64)
- VS Code: 1.131.0
- OS: Windows 11
Repro
- Open a workspace containing a file with a non-ASCII name, e.g.
docs/テスト.md, plus an ASCII one, e.g.docs/test.md. - Get a response that links both, i.e. containing
[docs/テスト.md](docs/テスト.md)and[docs/test.md](docs/test.md). - Click the ASCII link → the file opens in the editor. ✅
- Click the non-ASCII link → nothing happens. ❌
Cause
The webview renders responses with react-markdown, whose mdast→hast step runs normalizeUri on link destinations, percent-encoding non-ASCII characters. So the rendered href becomes:
docs/%E3%83%86%E3%82%B9%E3%83%88.md
The click handler passes that href to fileOpener.open, and openFile in the extension host resolves it without decoding (extension.js, v2.1.220):
async openFile(e, t) {
let r = On.isAbsolute(e) ? e : On.join(this.cwd, e);
...
It therefore stats <cwd>/docs/%E3%83%86%E3%82%B9%E3%83%88.md, which does not exist. The findFiles fallback further down is handed the same encoded string, so it produces no match either, and the click silently no-ops.
Suggested fix
Decode before resolving. To stay safe against filenames that legitimately contain %, only fall back to the decoded form when the literal path is missing and the decoded one exists:
let r = On.isAbsolute(e) ? e : On.join(this.cwd, e);
if (!Oi.existsSync(r)) {
try {
const d = decodeURIComponent(e);
if (d !== e) {
const r2 = On.isAbsolute(d) ? d : On.join(this.cwd, d);
if (Oi.existsSync(r2)) { e = d; r = r2; }
}
} catch {}
}
I applied exactly this as a local patch and non-ASCII links now open correctly.
Note
Absolute paths are also rejected, though for a different reason: the href→path parser uses /^([^:#]+?)(?:[:#]L?(\d+)(?:-L?(\d+))?)?$/, and the [^:#] class means a Windows path such as C:\... never matches, so those clicks fall through to openExternal.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗