Windows apply_patch invalid-base64 failures and silent large-file truncation

Open 💬 0 comments Opened Jul 22, 2026 by shpppsn2wk-cpu

Environment

  • Codex desktop app: OpenAI.Codex 26.715.8383.0
  • Platform: Microsoft Windows NT 10.0.26200.0, x64
  • PowerShell: 7.6.3
  • Surface: Codex desktop local workspace
  • Date reproduced: 2026-07-22

Summary

On Windows, apply_patch corrupts some large text-file edits in two ways. It
either fails before hunk matching because the filesystem bridge returns
undecodable dataBase64, or reports success after silently truncating the
target file. One-line edits to generated ASCII-only files reproduce both modes
without any repository source, secrets, logs, or user data.

Sanitized reproduction

  1. Run generate_repro.ps1. It creates synthetic_10000000_crlf.txt, exactly

10,000,000 bytes of deterministic ASCII filler. Its SHA-256 is
6BF7239738A80E81DBBFD4EEF1812F1752C7CFFFE22A662E013EF99FD3875017.

```powershell
param(
[long]$TargetSize = 10000000,
[string]$OutputPath = ""
)

if (-not $OutputPath) {
$OutputPath = Join-Path $PSScriptRoot (
"synthetic_{0}_crlf.txt" -f $TargetSize
)
}

$header = "PATCH_PROBE_ANCHOR = 0rn"
$bodyLine = (
"SAFE_SYNTHETIC_ASCII_CONTENT_0123456789" +
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz = fillerrn"
)
$encoding = [Text.Encoding]::ASCII
$remaining = $TargetSize - $encoding.GetByteCount($header)
$repeat = [Math]::Ceiling(
$remaining / $encoding.GetByteCount($bodyLine)
)
$bytes = $encoding.GetBytes($header + ($bodyLine * $repeat))
[Array]::Resize([ref]$bytes, $TargetSize)
[IO.File]::WriteAllBytes($OutputPath, $bytes)

Get-Item -LiteralPath $OutputPath | Select-Object FullName, Length
Get-FileHash -Algorithm SHA256 -LiteralPath $OutputPath
```

  1. Confirm that the first line is:

``text
PATCH_PROBE_ANCHOR = 0
``

  1. Use Codex apply_patch to replace only that line with:

``text
PATCH_PROBE_ANCHOR = 1
``

  1. To probe the intermittent silent-truncation range, regenerate with, for

example, ./generate_repro.ps1 -TargetSize 5991281. Record the byte length,
apply the same one-line patch, and record the byte length again even when the
tool reports success.

Actual result

The patch failed before applying the hunk in three consecutive attempts:

Failed to read file to update ...\synthetic_repro.txt:
fs/readFile returned invalid base64 dataBase64:
Invalid symbol 61, offset 8467288
Invalid symbol 61, offset 8459096
Invalid symbol 61, offset 8459095

Another sanitized boundary probe returned:

Invalid input length: 6004737

The explicit failed reads did not mutate their sanitized targets in the latest
probe. However, multiple calls that returned success changed the requested
first line and silently removed data from later in the file:

| Expected bytes | Actual bytes | Bytes lost | Tool result |
|---:|---:|---:|---|
| 4,194,304 | 4,194,304 | 0 | success |
| 4,456,448 | 4,087,808 | 368,640 | success |
| 4,503,552 | 4,405,248 | 98,304 | success |
| 4,600,000 | 4,415,680 | 184,320 | success |
| 4,650,000 | 4,244,495 | 405,505 | success |
| 4,716,000 | 4,445,664 | 270,336 | success |
| 5,991,281 | 4,989,809 | 1,001,472 | success |

The first line in every successful case changed from 0 to 1, proving the
patch ran. The unexpected byte loss occurred elsewhere in the target.

The sanitized successful-call truncations are sufficient to show that a
reported success can be destructive.

Expected result

The one-line edit should apply without changing unrelated bytes. A successful
result must never truncate the target. If the file is unsupported,
apply_patch should reject it before any mutation with a stable, explicit
size/capability error, and multi-file application should be atomic or clearly
transactional per target.

Investigation results

  • Reproduces using deterministic generated ASCII; proprietary source is not

involved.

  • Explicit failures occur before hunk matching, in the fs/readFile /

dataBase64 path.

  • Small files patch normally.
  • A 10,000,000-byte sanitized fixture failed in three consecutive attempts.

Around 5-6 MB, results were intermittent and changed with file/content/path
layout. CRLF and a literal equals sign are not independently required.

  • Nine nominally successful one-line probes silently truncated their targets;

losses ranged from 36,864 to 1,001,472 bytes.

  • The same edit mechanism can be avoided with a reviewed unified patch using

separate git apply --check and git apply operations.

  • Searching openai/codex issues for the exact error returned no duplicate on

2026-07-22. Existing Windows apply_patch issues concern sandbox latency,
split writable roots, or large patch payloads rather than large target-file
base64 decoding.

Root-cause assessment

Confirmed proximate cause: the patch engine's large-file read/write transaction
does not reliably preserve the complete target bytes. Some filesystem-bridge
payloads are rejected as invalid base64; other incomplete payloads are accepted,
patched, and written back as shorter files.

Inference requiring maintainer confirmation: the size/layout sensitivity,
varying offsets for identical bytes, and interior padding error are consistent
with independently encoded, truncated, or nondeterministically segmented chunks
being combined without preserving a valid single base64 stream. The client-side
evidence cannot identify the exact encoder, chunk boundary, scheduling condition,
or transport cap.

Suggested fix

  • Return raw bytes through a binary-safe transport or decode each independently

encoded chunk before concatenation.

  • If one base64 value is required, encode the complete byte sequence once and

validate its length before returning it.

  • Add regression tests around 4-7 MB text files with LF, CRLF, varied line

lengths, and file paths containing spaces.

  • Validate the complete pre-edit byte length/hash and the calculated post-edit

byte length before replacing the target. Write to a sibling temporary file,
validate it, then atomically replace the original.

  • Make multi-file patch failure atomic, or do not mutate any target until every

target has been read and all hunks have been validated.

  • Return an explicit target file exceeds supported patch-read size error if a

hard limit is intentional.

Current safe workaround

For affected large files, create one bounded unified patch, run
git apply --check, then run git apply separately. Immediately verify file
existence, hash/diff scope, and syntax. Do not include an affected large file in
a multi-file apply_patch call.

Privacy

This report and generator contain no project source, repository names, secrets,
account identifiers, session transcript, or original logs.

View original on GitHub ↗