[BUG] Write tool saves files as UTF-8 without BOM, causing encoding corruption in Windows development tools (Delphi IDE, SSMS)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Summary
The Write tool in Claude Code saves all generated files (.pas, .dfm, .sql, and others) as UTF-8 without BOM (Byte
Order Mark). On Windows, many development tools default to ANSI/Windows-1252 when no BOM is present, causing silent data corruption of any non-ASCII characters in the generated files.
Environment
- OS: Windows 11 Pro
- Shell: bash (Git Bash / MSYS2)
- Affected tools: Delphi 12 Athens IDE, SQL Server Management Studio (SSMS) 19+
- Claude Code version: 2.1.51
Steps to Reproduce
Scenario A — Delphi source file (.pas)
- Ask Claude Code to create a .pas file containing a Spanish/accented string literal, e.g.:
MessageBox(0, '¿Desea continuar?', 'Confirmación', MB_YESNO);
- Claude Code creates the file as UTF-8 without BOM (verifiable with a hex editor: no EF BB BF prefix).
- Open the .pas file in Delphi 12 Athens IDE.
- Delphi reads the file as ANSI (Windows-1252) because there is no BOM.
- Result: The string renders as ¿Desea continuar? / Confirmación at runtime.
Scenario B — SQL script (.sql)
- Ask Claude Code to create a .sql file with Unicode string literals:
INSERT INTO TABLE VALUES (N'Día de Año Nuevo');
- Claude Code saves the file as UTF-8 without BOM.
- Open and execute the script in SSMS.
- SSMS reads the file as ANSI; the UTF-8 byte sequences for í (0xC3 0xAD) are interpreted as two Latin-1 characters
(Ã + soft-hyphen).
- Result: The database stores DÃa de Año Nuevo — even though the correct N'' Unicode prefix is present.
Scenario C — Delphi form file (.dfm)
- Ask Claude Code to create a .dfm file with a caption containing accented characters:
Caption = 'Médicos'
- Claude Code saves as UTF-8 without BOM.
- Delphi compiles the form reading the DFM as ANSI.
- Result: The caption renders as Médicos at runtime.
Root Cause
Files written by the Write tool are encoded as UTF-8 without BOM. On Windows, tools that do not implement encoding auto-detection fall back to the system ANSI code page (Windows-1252 / CP1252). The multi-byte UTF-8 sequences for characters above U+007F are then interpreted as multiple single-byte Latin-1 characters, producing garbled text that is silently written to the file, database, or compiled binary.
Expected Behavior
One of the following:
- (Preferred) The Write tool adds a UTF-8 BOM (EF BB BF) to text files on Windows, matching the default behavior of
Delphi 12, Visual Studio, and most Windows-native editors.
- The Write tool exposes a parameter to control the output encoding (e.g., encoding: "utf-8-bom" | "utf-16-le" |
"utf-8").
- The Write tool detects the file extension and applies the appropriate encoding for well-known formats that expect
BOM on Windows (.pas, .dfm, .dpr, .sql, .cs, .vb, etc.).
Actual Behavior
All files are saved as UTF-8 without BOM regardless of extension, platform, or content.
Impact
- Silent corruption: No error or warning is shown during file creation.
- Hard to diagnose: The files look correct when viewed in UTF-8-aware editors (VS Code, Notepad++) but fail in tools
that default to ANSI.
- Affects Windows developers using any IDE or tool that relies on BOM for encoding detection: Delphi, RAD Studio,
Visual Studio (legacy projects), SQL Server Management Studio, classic Notepad, etc.
Workaround (current)
Use #NNN escape notation for all non-ASCII characters in Delphi string literals (encoding-agnostic):
// Instead of: '¿Desea continuar?'
// Use: #191'Desea continuar?'
For SQL, use NCHAR() function or ensure the file is re-saved as UTF-16 in SSMS before execution.
What Should Happen?
You must save the accented characters correctly.
Error Messages/Logs
Steps to Reproduce
Steps to Reproduce
Prerequisites
- Windows 10 or Windows 11
- Claude Code installed
- A hex editor or the PowerShell command Format-Hex (built into Windows)
---
Reproduce in 3 steps (minimal example)
- Ask Claude Code to create a file containing non-ASCII characters:
Use this exact prompt in Claude Code:
Create a file called test_encoding.pas with this exact content:
unit test_encoding;
interface
implementation
procedure Test;
begin
ShowMessage('¿Cómo estás? Día de Año Nuevo');
end;
end.
- Inspect the file encoding with PowerShell:
Open PowerShell and run:
# Check the first 4 bytes of the file (BOM detection)
Format-Hex "test_encoding.pas" | Select-Object -First 1
Expected output (UTF-8 with BOM):
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 EF BB BF 75 6E 69 74 20 74 65 73 74 5F 65 6E 63 unit test_enc
(First 3 bytes must be EF BB BF — the UTF-8 BOM)
Actual output (UTF-8 without BOM):
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 75 6E 69 74 20 74 65 73 74 5F 65 6E 63 6F 64 69 unit test_encodi
(No BOM — file starts directly with 75 = u)
- Verify the corruption in a Windows tool:
Open test_encoding.pas in Notepad (not Notepad++, not VS Code — plain notepad.exe) and observe:
- Expected: '¿Cómo estás? Día de Año Nuevo'
- Actual: '¿Cómo estás? DÃa de Año Nuevo'
---
Reproduce the SQL corruption (real-world impact)
- Ask Claude Code to create a SQL file:
Create a file called test_unicode.sql with this content:
USE master;
INSERT INTO test_table (nombre) VALUES (N'José García');
INSERT INTO test_table (nombre) VALUES (N'Año Nuevo');
- Check encoding:
Format-Hex "test_unicode.sql" | Select-Object -First 1
(Same result: no BOM — first bytes are 55 53 45 = USE)
- Open and execute in SSMS:
- Open the file in SQL Server Management Studio (File → Open → File...)
- SSMS status bar will show "ANSI" encoding (not UTF-8)
- Execute the script
- Query the table: SELECT * FROM test_table
- Result: José GarcÃa / Año Nuevo stored in the database — data permanently corrupted despite the correct N''
Unicode prefix
Reproduce the Delphi Form file (.dfm) corruption
- Ask Claude Code to create a .dfm file:
Create a file called test_form.dfm with this exact content:
object TestForm: TTestForm
Caption = 'Gestión de Médicos'
object Label1: TLabel
Caption = 'Dirección:'
end
object Label2: TLabel
Caption = 'Año de nacimiento:'
end
object Label3: TLabel
Caption = 'Número de cédula:'
end
end
- Check encoding:
Format-Hex "test_form.dfm" | Select-Object -First 1
(Result: no BOM — file starts with 6F 62 6A = obj)
- Verify the corruption in Notepad:
Open test_form.dfm in plain notepad.exe:
- Expected: Caption = 'Gestión de Médicos'
- Actual: Caption = 'Gestión de Médicos'
- Real-world impact in Delphi 12:
When Delphi compiles this .dfm reading it as ANSI, the captions render at runtime as:
- Gestión de Médicos (form title)
- Dirección: (label)
- Año de nacimiento: (label)
- Número de cédula: (label)
---
One-liner verification (no extra tools needed)
# Ask Claude Code to write any file with accented characters, then run:
$bytes = [System.IO.File]::ReadAllBytes("test_encoding.pas")
if ($bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
Write-Host "PASS: UTF-8 with BOM" -ForegroundColor Green
} else {
Write-Host "FAIL: UTF-8 without BOM (first bytes: {0:X2} {1:X2} {2:X2})" -f $bytes[0], $bytes[1], $bytes[2]
-ForegroundColor Red
}
Output: FAIL: UTF-8 without BOM (first bytes: 75 6E 69)
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.51
Platform
Other
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗