anomalyco / anomalyco/opencode
edit and apply_patch silently corrupt non-UTF-8 files (U+FFFD replacement)
@neriousy is already working on this.
Since Aug 28, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Describe the bug
edit and apply_patch decode file bytes with a non-fatal UTF-8 decoder (new TextDecoder("utf-8") and new TextDecoder("utf-8", { ignoreBOM: true })). Invalid sequences are silently replaced with U+FFFD.
When oldString matches an ASCII region of a file that contains non-UTF-8 bytes elsewhere (GBK/Latin-1 comments, legacy strings, stray bytes), the tool reports success and writes the entire file back as U+FFFD, permanently destroying every non-UTF-8 byte.
The read tool already rejects this with MalformedUtf8Error (File is not valid UTF-8) via a fatal decoder, but edit/apply_patch don't — so a file that read refuses is silently corrupted by edit.
Steps to reproduce
- Create a file with bytes
const x = 1\nfollowed by GBK bytesd6 d0 ce c4(中文). - edit
oldString: "const x = 1"→newString: "const y = 1". - The file is written back with the GBK bytes replaced by U+FFFD, and the tool reports success.
Affected code
packages/core/src/tool/edit.ts—decodeUtf8usesnew TextDecoder()packages/core/src/tool/apply-patch.ts—new TextDecoder("utf-8", { ignoreBOM: true })
Suggested fix
Decode with { fatal: true } and fail with an explicit "file is not valid UTF-8" error, leaving the file untouched (matching read).
Environment
- opencode version: latest dev
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.