github / github/copilot-cli

`edit` tool silently fails with "No match found" when `old_str` contains CJK typographic quotes

Open
#3,254 0 comments 0 reactions 0 assignees View on GitHub
area:tools
Dominant language
Shell
Stars
11.2k
Forks
1.9k
Avg merge
14h 16m
Merged PRs (30d)
6

Description

### Describe the bug

**Summary**

The `edit` tool returns `No match found` when `old_str` spans a region containing
Unicode typographic (curly) quotation marks — specifically U+201C `\u201c`
(LEFT DOUBLE QUOTATION MARK) and U+201D `\u201d` (RIGHT DOUBLE QUOTATION MARK).
The same edit succeeds when the target region contains only ASCII characters.

### Affected version

v1.0.44

### Steps to reproduce the behavior

**Reproduction**

Given a UTF-8 file `test.md` containing:

```text
Please do not re-examine \u201cwhat repo to change\u201d each time.
```

The following tool call fails:

```json
{
"old_str": "Please do not re-examine \"what repo to change\" each time.",
"new_str": "Please do not re-examine \"what repo to change\" each session."
}
```

Error: `No match found`

### Expected behavior

No error occur, and edit success at the first time.

### Additional context

**Environment**
- GitHub Copilot CLI (terminal coding agent), v1.0.44
- OS: Windows 11, PowerShell 7
- File encoding: UTF-8 LF (no BOM)

**Root cause (hypothesis)**

The LLM generates `old_str` from text it received through the `view` tool.
Typographic quotes (U+201C/U+201D) are visually identical to ASCII `"` (U+0022)
but are distinct Unicode code points. At some stage in the tool-call pipeline —
likely during tokenization or JSON argument serialization — U+201C/U+201D are
normalized to U+0022, causing an exact-match failure against the unmodified file
content.

**Evidence**

- 3/3 edit calls failed where `old_str` overlapped a region containing U+201C/U+201D
- 3/3 edit calls succeeded on the same files where `old_str` avoided those characters
- 100% correlation; no other differing factor (same session, same tool, same model)

**Impact**

- Every `edit` targeting a line with CJK or typographic quotes fails silently
- Error message `No match found` gives no character-level diagnosis
- LLM cannot self-correct without explicit human intervention
- Especially common in East Asian language repositories where typographic quotes
are grammatically standard

**Requested changes**

### 1. Richer error diagnostics (low risk — no behavior change)

When `old_str` is not found, include:
- Line number of the closest substring match
- Character positions that differ
- Unicode code points of mismatched characters
- Hint if the diff involves known typographic/ASCII quote equivalents

Example improved error:
```
Edit failed: old_str not found in file.
Closest match at line 20 (1 character mismatch at position 28):
File: ... \xE2\x80\x9C (U+201C LEFT DOUBLE QUOTATION MARK)
old_str: ... \x22 (U+0022 QUOTATION MARK)
Hint: the file uses typographic quotes. Consider using str.replace() in Python.
```

### 2. Optional quote-folding mode (enhancement — opt-in)

Add an optional `unicode_quote_fold: true` flag that normalizes both `old_str` and
file content through a typographic→ASCII quote mapping before matching (without
altering what is written to disk).

**Workaround (current)**

Use Python `Path.read_text(encoding='utf-8').replace(...).write_text(...)`.
Functional but requires extra steps and is not self-correcting.
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.