claude-code - 💡(How to fix) Fix [VSCode Extension] Markdown links to files with non-ASCII (e.g. Japanese) filenames fail silently to open

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

In the VSCode extension (v2.1.161), clicking a markdown link in the chat that points to a file with non-ASCII characters in its path (e.g. Japanese, Chinese, Korean filenames) does nothing. The click is intercepted but the file is not opened in the editor.

ASCII-only paths work correctly.

Error Message

Actual: Nothing happens. No error message, no editor open.

Root Cause

Traced through extension.js and webview/index.js (v2.1.161):

  1. The markdown parser (micromark/remark) percent-encodes non-ASCII URL characters per CommonMark spec → React component receives href="%E8%AD%B0...%E9%8C%B2.md".
  2. The webview click handler (ox() regex parser) accepts the encoded string as a valid file path (it ends in .md) and passes it to fileOpener.open().
  3. The RPC sends {type: "open_file", filePath: "%E8...%E9%8C%B2.md"} to the extension.
  4. In extension.js, the openFile(z, V) handler does:
    let N = path.isAbsolute(z) ? z : path.join(this.cwd, z);
    // N is now `/cwd/some_dir/%E8...%E9%8C%B2.md` which does NOT exist on disk
    // The actual file is `/cwd/some_dir/議事録.md`
  5. fs.existsSync(N) returns false. The findFiles fallback also fails because it searches with the encoded glob, not the decoded name.
  6. fs.statSync(N) inside try{...}catch{} throws (file missing); the catch swallows it.
  7. vscode.window.showTextDocument(Uri.file(N)) is called with the non-existent path → silently fails (no toast, no log).

Code Example

let N = path.isAbsolute(z) ? z : path.join(this.cwd, z);
   // N is now `/cwd/some_dir/%E8...%E9%8C%B2.md` which does NOT exist on disk
   // The actual file is `/cwd/some_dir/議事録.md`

---

openFile(z, V) {
  let decoded;
  try { decoded = decodeURIComponent(z); } catch { decoded = z; }
  let N = path.isAbsolute(decoded) ? decoded : path.join(this.cwd, decoded);
  // ... rest unchanged
}
RAW_BUFFERClick to expand / collapse

Summary

In the VSCode extension (v2.1.161), clicking a markdown link in the chat that points to a file with non-ASCII characters in its path (e.g. Japanese, Chinese, Korean filenames) does nothing. The click is intercepted but the file is not opened in the editor.

ASCII-only paths work correctly.

Environment

  • Extension: anthropic.claude-code v2.1.161 (darwin-arm64)
  • VSCode: latest
  • OS: macOS 14 (Darwin 24.6.0)
  • Repro file path: /path/to/workspace/some_dir/20260520_千葉様ヒアリング_議事録.md

Reproduction

  1. Have a workspace file with non-ASCII characters in the filename (e.g. 議事録.md)
  2. In Claude Code chat, the assistant outputs a markdown link: [議事録](some_dir/議事録.md)
  3. Click the link

Expected: File opens in the editor (same as ASCII-named files). Actual: Nothing happens. No error message, no editor open.

Right-clicking the link → "Copy Link" returns the percent-encoded path (some_dir/%E8%AD%B0%E4%BA%8B%E9%8C%B2.md), which confirms encoding is happening in the rendering pipeline.

Root Cause

Traced through extension.js and webview/index.js (v2.1.161):

  1. The markdown parser (micromark/remark) percent-encodes non-ASCII URL characters per CommonMark spec → React component receives href="%E8%AD%B0...%E9%8C%B2.md".
  2. The webview click handler (ox() regex parser) accepts the encoded string as a valid file path (it ends in .md) and passes it to fileOpener.open().
  3. The RPC sends {type: "open_file", filePath: "%E8...%E9%8C%B2.md"} to the extension.
  4. In extension.js, the openFile(z, V) handler does:
    let N = path.isAbsolute(z) ? z : path.join(this.cwd, z);
    // N is now `/cwd/some_dir/%E8...%E9%8C%B2.md` which does NOT exist on disk
    // The actual file is `/cwd/some_dir/議事録.md`
  5. fs.existsSync(N) returns false. The findFiles fallback also fails because it searches with the encoded glob, not the decoded name.
  6. fs.statSync(N) inside try{...}catch{} throws (file missing); the catch swallows it.
  7. vscode.window.showTextDocument(Uri.file(N)) is called with the non-existent path → silently fails (no toast, no log).

Suggested Fix

In openFile(z, V), decode the incoming path before resolving:

openFile(z, V) {
  let decoded;
  try { decoded = decodeURIComponent(z); } catch { decoded = z; }
  let N = path.isAbsolute(decoded) ? decoded : path.join(this.cwd, decoded);
  // ... rest unchanged
}

Alternatively, decode in the webview before sending the RPC.

Tested Variants (all NG in v2.1.161)

#FormatResult
1[t](dir/議事録.md) (raw Japanese, relative)
2[t](dir/%E8%AD%B0%E4%BA%8B%E9%8C%B2.md) (pre-encoded)
3[t](./dir/議事録.md) (with ./)
4[t](<dir/議事録.md>) (angle brackets)
5[t](/abs/path/議事録.md) (absolute)
6[t](file:///abs/path/議事録.md)
7[t](議事録.md) (filename only, findFiles fallback)

Impact

Non-ASCII filenames are common for users working in Japanese / Chinese / Korean / Cyrillic etc. The assistant's instruction to "use markdown link syntax to make files clickable" silently fails for these users.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING