You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
edit reports success for a CRLF-only line-ending change that does nothing #45927
In the edit tool, the oldString === newString guard runs on the raw input before CRLF normalization. On a CRLF file, oldString and newString that differ only in line-ending style are normalized to the same CRLF text, so the replacement becomes the identity function.
The tool then reports Replacements: 1 (success) while the file is unchanged — the model believes it applied a change (e.g. normalizing line endings) that never happened.
Steps to reproduce
CRLF file containing a\r\nb. Edit with oldString: "a\r\nb", newString: "a\nb".
Expected: either a change or a clear error. Actual: success with Replacements: 1, file unchanged.
Affected code
packages/core/src/tool/edit.ts — the identity check at the top of execute vs. the convertToLineEnding normalization further down.
Suggested fix
Re-check oldString === newString after normalization, or detect the identity replacement and return a no-op error instead of reporting success.
The same defect is on v2, at packages/core/src/tool/plugin/edit.ts. The raw check sits at line 135 and the line-ending conversion at lines 169-170.
Measured on v2 at f94eefa, through the registered tool. The file is CRLF and holds before\r\nrest\r\n. The call passes oldString: "before\r\nrest" and newString: "before\nrest".
I can't reproduce this on current dev — the identity guard inside replace() (packages/opencode/src/tool/edit.ts:683) already rejects this case with No changes to apply: oldString and newString are identical., and the file is left untouched. Verified with a test against a CRLF file (a\r\nb, oldString: "a\r\nb", newString: "a\nb"): it errors instead of reporting success, so the guard fires before any replacement happens. For what it's worth this path is unaffected by #53253, which only changes ending detection for mixed-ending files.
So on dev this looks fixed or unreachable; the live defect seems to be the v2 copy of the tool that @devYRPauli pointed at (packages/core/src/tool/plugin/edit.ts).
packages/opencode/src/tool/edit.ts:683 is the v1 tool. This issue is about the core tool, packages/core/src/tool/edit.ts, and that file still has the defect on dev.
At ecc4916, the core tool compares the raw strings at line 127 and converts the line endings at lines 163-164. Nothing compares the strings again after the conversion. The v1 tool converts first, at lines 130-131, so its replace() guard sees the converted strings. That is why your test errors.
The core file has not changed since 5691f36 (2026-06-30). On 2026-10-05 I ran the reproduction again on dev at 907b3bc. The core tool still reported one replacement and left the file unchanged.
#46849 fixes the core tool on dev, and #47088 fixes the v2 copy at packages/core/src/tool/plugin/edit.ts. The cleanup bot closed both PRs, and I asked for a reopen on each.
Activity
github-actions commentedon Aug 28, 2026
This issue might be related to existing issues. Please check:
edittool + CRLF normalization area (convertToLineEnding+detectLineEndinginteraction). That issue focuses on match failure; this one focuses on a false-success no-op whenoldStringandnewStringnormalize to the same content. They share root cause and a fix for either would likely need to address both.devYRPauli commentedon Sep 3, 2026
The same defect is on
v2, atpackages/core/src/tool/plugin/edit.ts. The raw check sits at line 135 and the line-ending conversion at lines 169-170.Measured on
v2at f94eefa, through the registered tool. The file is CRLF and holdsbefore\r\nrest\r\n. The call passesoldString: "before\r\nrest"andnewString: "before\nrest".On
v2the tool also asks for edit approval and writes the file back before it reports the replacement.#46849 fixes this on
dev. #47088 fixes it onv2. The tool file moved between the two branches, so one diff does not cover the other.fix(core): keep unchanged line endings and allow explicit line-ending…
ggbdpq commentedon Oct 6, 2026
I can't reproduce this on current
dev— the identity guard insidereplace()(packages/opencode/src/tool/edit.ts:683) already rejects this case withNo changes to apply: oldString and newString are identical., and the file is left untouched. Verified with a test against a CRLF file (a\r\nb,oldString: "a\r\nb",newString: "a\nb"): it errors instead of reporting success, so the guard fires before any replacement happens. For what it's worth this path is unaffected by #53253, which only changes ending detection for mixed-ending files.So on
devthis looks fixed or unreachable; the live defect seems to be the v2 copy of the tool that @devYRPauli pointed at (packages/core/src/tool/plugin/edit.ts).devYRPauli commentedon Oct 7, 2026
packages/opencode/src/tool/edit.ts:683is the v1 tool. This issue is about the core tool,packages/core/src/tool/edit.ts, and that file still has the defect ondev.At ecc4916, the core tool compares the raw strings at line 127 and converts the line endings at lines 163-164. Nothing compares the strings again after the conversion. The v1 tool converts first, at lines 130-131, so its
replace()guard sees the converted strings. That is why your test errors.The core file has not changed since 5691f36 (2026-06-30). On 2026-10-05 I ran the reproduction again on
devat 907b3bc. The core tool still reported one replacement and left the file unchanged.#46849 fixes the core tool on
dev, and #47088 fixes the v2 copy atpackages/core/src/tool/plugin/edit.ts. The cleanup bot closed both PRs, and I asked for a reopen on each.