Patched files have mixed line endings on Windows

Open 💬 24 comments Opened Sep 21, 2025 by chausner
💡 Likely answer: A maintainer (cnaples79, contributor) responded on this thread — see the highlighted reply below.

What version of Codex is running?

0.39.0

Which model were you using?

gpt5 (medium)

What platform is your computer?

Microsoft Windows NT 10.0.26120.0 x64

What steps can reproduce the bug?

When codex makes changes to files, it does not adhere to the line endings in the file but appears to alway use Unix-style LF. On Windows with files using CRLF, this leads to inconsistent line endings in the file. When opening these files in Visual Studio, for example, VS warns about this fact and asks whether line endings should be normalized.

What is the expected behavior?

codex should use LF line endings, if the file already uses LF line endings, and CRLF endings if the file already uses CRLF endings.

What do you see instead?

_No response_

Additional information

_No response_

View original on GitHub ↗

24 Comments

cnaples79 contributor · 10 months ago

I've submitted a PR for this issue/bug.

chausner · 10 months ago

@cnaples79 Thanks a lot for the quick fix!

etraut-openai contributor · 7 months ago

This issue is fixed in 0.66.0.

mrexodia · 5 months ago

For me it still happens that codex forces LF line endings on files that are 100% CRLF:

<img width="769" height="445" alt="Image" src="https://github.com/user-attachments/assets/5d6ebe12-2dc2-498a-bc90-e57ebe34a553" />

Thread id: 019bf494-e540-71e3-8e23-7005d9dae39c. I am running codex 0.87.0 on Windows

jta5456 · 4 months ago

This is still frequently happening to me as well. I would think we could just detect which line ending is more frequently used in the current file, instead of the proposed "adding another setting".

john-preston · 4 months ago

This still happens in latest Codex in Windows Codex app.

tigrom · 4 months ago

This is definetly extremly anoying !!!!!!!! It is almost imposible to let it edit!!

xingwangyong · 4 months ago

This bug makes the codex diff completely useless

mmiladinov12 · 3 months ago

Issue still persists. Codex is changing files with CRLF -> LF

thirumaleshp · 3 months ago

I investigated the regression reported in v0.87.0 and found the root cause in codex-rs/apply-patch/src/lib.rs, function derive_new_contents_from_chunks:

  1. split('\n') preserves trailing \r on original lines from CRLF files
  2. Patch content from the parser (which uses .lines()) never contains \r
  3. apply_replacements splices in new lines (no \r) replacing old lines (with \r)
  4. join("\n") → unchanged lines get \r\n, changed lines get bare \nmixed endings

Fix: Detect consistent CRLF usage, normalize to LF before matching, then re-join with the original line ending style. Only treats a file as CRLF when every \n is preceded by \r (avoids false positives from embedded \r in string literals).

Branch with fix + 3 tests: https://github.com/thirumaleshp/codex/tree/fix/preserve-crlf-line-endings

Diff: https://github.com/openai/codex/compare/main...thirumaleshp:codex:fix/preserve-crlf-line-endings

Happy to open a PR if given collaborator access, or feel free to cherry-pick the commit.

tigrom · 3 months ago

IMO, the correct behavior would be to leave existing EOLs unchanged, even if they are inconsistent. It should not start normalizing EOLs that are already there.

So when the user requests changes via Codex, only the affected lines should be modified. Any existing EOLs should be preserved, even if they are inconsistent.
That’s the main reason of the bug.

chk-mk · 2 months ago

This is still happening as of 0.121.0, and still extremely annoying.

stsrki · 2 months ago

Can the line endings be part of the .codex/config.toml file so that we can at least define default line endings, and possibly an EOF, that we configure and not allow codex to hallucinate what it thinks is the best choice?

AndrewSav · 2 months ago

When you work on Windows with Visual Studio apply_patch also routinely ruins BOM for some reason, at the same time as it introduces mixed ending.

SailAwayWine · 2 months ago

I reproduced this on Windows with a byte-level line-ending count, and the behavior points to the internal apply-patch implementation.

The apply-patch path appears to run through Codex’s internal --codex-run-as-apply-patch mode:

pub const CODEX_CORE_APPLY_PATCH_ARG1: &str = "--codex-run-as-apply-patch";

Source:
https://github.com/openai/codex/blob/9ea38136b00937a87c94cbcaab872342b2adb6d9/codex-rs/apply-patch/src/lib.rs#L44

I tested an existing CRLF text file and counted line endings at the byte level:

Before apply_patch:
LF=104
CRLF=104

After a one-line apply_patch edit:
LF=104
CRLF=103

After manual CRLF normalization:
LF=104
CRLF=104

Interpretation:

  • Before patching, every LF byte was part of a CRLF sequence, so the file was clean CRLF.
  • After patching, there were still 104 LF bytes but only 103 CRLF sequences, meaning one line became LF-only.

The likely source of the problem is in derive_new_contents_from_chunks. The implementation reads the file as text, splits on \n, applies replacements, and then rebuilds the file with join("\n"):

let mut original_lines: Vec<String> = original_contents.split('\n').map(String::from).collect();

The specific problematic line appears to be this:

let new_contents = new_lines.join("\n");

Source:
https://github.com/openai/codex/blob/9ea38136b00937a87c94cbcaab872342b2adb6d9/codex-rs/apply-patch/src/lib.rs#L657-L684

This joins all internal lines with LF. For unchanged CRLF lines, that happens to work because split('\n') leaves the trailing \r attached to the line content. But inserted/replacement patch lines do not have that trailing \r, so they become LF-only when joined.

A minimal fix may not need to rewrite the whole line model. Since existing CRLF lines already retain their trailing \r after split('\n'), the current join("\n") happens to preserve unchanged CRLF lines correctly. The mixed-ending problem appears when inserted/replacement patch lines are added without the trailing \r.

A low-risk fix could be:

  • Detect whether the target file uses CRLF.
  • When building replacement/inserted lines for that file, append \r to patch-provided lines before they are merged into new_lines.
  • Leave the existing join("\n") behavior unchanged.
let uses_crlf = original_contents.contains("\r\n");

fn adapt_patch_line(line: String, uses_crlf: bool) -> String {
    if uses_crlf && !line.ends_with('\r') {
        format!("{line}\r")
    } else {
        line
    }
}

That should preserve current behavior for LF files while preventing inserted/replacement lines from becoming LF-only in CRLF files.

This is especially visible on Windows because IDEs such as Visual Studio warn immediately when a file has mixed line endings.

Current workaround on my side is to force the agent (in the global agents.md) to normalize immediately after using the patch tool:

This is a Windows computer. For text files, including source files, project files, Notepad files, HTML, CSS, JavaScript, XML, JSON, Markdown, config files, and scripts, CRLF is the only supported line-ending convention.

When using apply_patch/--codex-run-as-apply-patch, normalize every touched text file to CRLF before running diff review, build/test verification, or considering the edit complete.

This workaround is effective, but it is still a workaround: apply_patch first creates mixed line endings, then a separate recovery step repairs the touched file before any diff review or task completion.

Enirsa · 2 months ago

please, guys, fix this

meum · 1 month ago
This workaround is effective, but it is still a workaround: apply_patch first creates mixed line endings, then a separate recovery step repairs the touched file before any diff review or task completion.

I tried the workaround but i still see a lot of unchanged lines showing up as changed in the diff that codex shows.

It looks like @dylan-hurd-oai has been working on a fix in https://github.com/openai/codex/pull/11416 and https://github.com/openai/codex/pull/15035, but no changes in those branches for 2 months 🙁

elachlan · 1 month ago

I am wasting tokens fixing line endings. Can someone please fix this asap? My expectation is that the files line endings be preserved, with the patched lines honoring the existing line endings. A config option would be nice. I tried using .editorconfig and .gitattributes with the expectation that codex would honor it. It did not.

Saigut · 1 month ago

How it’s going?

toddlucas · 1 month ago

This is why dog fooding is so important. It's obvious that people inside OpenAI are not using Windows for development. This would have been fixed last year if that were the case. It's fine if everyone there uses Macs. But when half of your customer base uses Windows, that's a fail.

n00mkrad · 1 month ago

So... any news? It's been months and you still have to waste tokens on telling your agent what kind of line endings to use.

mangotonk · 20 days ago

yup this is still broken as far as i can tell, creating abomination mixed line ending files. unless there is a config option im not seeing

orazdow · 1 day ago

I'm spending the majority of my time normalizing line endings and aborting codex edits because it's own mixed line endings send it into confusion. This is completely broken.

n00mkrad · 1 day ago
I'm spending the majority of my time normalizing line endings and aborting codex edits because it's own mixed line endings send it into confusion. This is completely broken.

My solution was to have Codex write a hook that checks for all modified (git) files and normalizes them (within the hook, in python, no tokens wasted).

Much better than wasting time and tokens on having the agent do it.