CRLF vs LF And the Two Bytes That Break Things
The error message never mentions line endings. It names a file that plainly exists and appears to be spelled correctly.
Two characters nobody can see decide whether a file works. Windows ends a line with CRLF, a carriage return followed by a line feed. Unix, Linux and macOS all use LF alone. Nothing on screen tells you which you are holding. When it matters, the error message never mentions line endings, which is why this costs people so much time.
It matters more with mail than with almost anything else, in the direction people least expect. A mailbox on a Mac carries Windows style endings. That is correct rather than a mistake somebody made.
Where CRLF And LF Came From And Why Both Survived
On a teletype, moving to the next line took two separate movements. The carriage went back to the left, then the paper rolled up by one line. Two mechanical actions, so the character set gave each one its own code.
| Character | Byte | What the machine did |
|---|---|---|
| Carriage return, CR | 0D | Move back to the left margin |
| Line feed, LF | 0A | Roll the paper up one line |
Different systems then chose differently. None of them changed their mind.
Windows Hello<CR><LF>World<CR><LF> 0D 0A
Unix, macOS Hello<LF>World<LF> 0A
Classic Mac Hello<CR>World<CR> 0D
Apple switched sides in 2001. Classic Mac OS used the carriage return alone. Mac OS X was built on Unix and took the line feed, so files from before that era behave differently from files after it. Anything old enough to predate the change can still turn up using neither of the current conventions.
Why Mail Insists on CRLF
This is the part that catches people working with mail files, because it runs against every other habit.
The internet message format demands both characters at the end of every line. Not as a preference. The specification says lines are terminated by a carriage return followed by a line feed. Mail servers were built on that promise.
Mail Files Use Both
- EML, every header and body line
- MBOX, including the From lines
- MHT, since it is the same container
- Anything a mail server handed over
Which Means
- A mailbox on a Mac still has them
- Converting to line feeds breaks the format
- A tidy up script can invalidate a file
- Nothing looks different afterwards
The MIME boundary is where it shows first. A boundary marker has to match exactly for the parts of a message to be found. Change the line endings and the match can fail, so a message that held three attachments arrives holding none, with nothing to suggest what happened.
What a Stray CR Does to a File
The character does not vanish when a program does not expect it. It becomes part of whatever was on that line, which is where the strange errors come from.
| Where it lands | What you see |
|---|---|
| A script's first line | An interpreter not found error, for a program that is installed |
| A filename in a list | A file not found error for a name that looks right |
| A password in a config file | Authentication fails with correct credentials |
| The last column of a CSV | A trailing character on every value in that column |
| A terminal display | A caret and an M at the end of each line |
Every row has the same shape. The visible part is correct and something invisible is attached to it, so the error describes a thing that plainly exists and appears to be spelled right.
That last row is the one worth recognising on sight. It means a Windows file being read by something that wants line feeds, nothing more. It is not damage and nothing needs repairing. The file is fine and the reader is strict.
Why Git Reacts So Badly to Line Endings
Anybody who has opened a change and found every line marked as modified has met this.
Version control compares lines. Change the ending on all of them and every line differs from the stored version, so the whole file reads as rewritten. The visible text is identical and the comparison is still correct, because the bytes really did all change.
What it looks like
An alarming change412 lines removed
412 lines added
every line touched
nothing readable
actually differs
Reviewing this is impossible. The real change, if there was one, is buried in four hundred lines of noise.
What happened
One settingthe file was opened
and saved by an
editor with different
defaults
two bytes became one
on every line
Nobody edited anything. An editor applied its own convention on save, as it was configured to.
Checking Line Endings Without Changing Anything
- Read the editor status bar. VS Code shows CRLF or LF in the bottom right. Notepad++ shows it too. Both let you switch. Looking costs nothing.
- Use the file command on a terminal. It reports CRLF line terminators when they are there and says nothing when they are not, which is the answer either way.
- Look at the hex if you want certainty. 0D 0A is both characters. 0A alone is a line feed. This is the only method that cannot be wrong.
- Check what the destination needs before converting. A server, a script or version control wants line feeds. Mail and older Windows tools want both. Converting without asking is how the trouble starts.
Converting is safe and reversible in one direction only. Going from both characters to one is a clean removal. Going back adds a carriage return to every line, including lines that never had one, so a file that mixed the two conventions comes out consistent rather than restored.
Read next CSV And the Four Things It Never Tells You The format where a line break inside a value is legal. Also where that causes most trouble.Where Line Endings Meet the Other Invisible Problem
Line endings and character encoding cause similar trouble for a similar reason. Both are decisions about bytes that a file usually does not declare. Both stay invisible until something strict reads it.
They are not the same problem. Encoding decides which character a byte means. Line endings decide how many bytes end a line. A file can be wrong on one and right on the other. The symptoms look nothing alike.
| Symptom | Which one |
|---|---|
| Accents show as odd symbols | Encoding |
| Everything runs together on one line | Line endings |
| A caret and an M at every line end | Line endings |
| A question mark in a diamond | Encoding, unrecoverable |
| A script fails naming a program that exists | Line endings |
Where the file happens to be a mailbox, both rules apply at once and pull opposite ways. The encoding is declared per part and should be honoured. The line endings are fixed by the specification and should be left alone. Our file viewers read both as they are rather than normalising anything. The converters keep whichever endings the destination format requires.
Behaviour checked against RFC 5322 and the referenced articles in August 2026. The symptoms described were reproduced in a current shell and editor.
Questions People Ask
7 questions, answered in full below.What is the difference between CRLF and LF?
CRLF is two characters. A carriage return then a line feed. LF is that second one on its own. Windows writes both while Unix and macOS write one. Nothing on screen distinguishes them, because neither character is visible.
Why does my file show as one long line?
Because it uses line feeds only and the program reading it expects both characters. Older Windows tools do this. Modern Notepad handles it, so a file that runs together in one editor and looks fine in another has told you which endings it uses.
Why does my script fail with a strange error?
Because the carriage return became part of something. The interpreter path on the first line gains an invisible character, so the system looks for a program whose name ends in one and reports that it does not exist. The message names the right file and never mentions the reason.
Which should I use?
Whatever the destination expects. Line feeds alone for anything crossing to a server, going into version control or being read by a script. Both characters where mail or an old Windows tool has to read it, because those genuinely require them.
Does this affect email files?
Directly. It also runs opposite to everything else. The message format requires both characters, so a mail file on a Mac still carries Windows style endings. Converting a mailbox to line feeds alone leaves something that is no longer a valid message.
How do I see which endings a file uses?
Most editors say so in the status bar, showing CRLF or LF. On a terminal the file command reports CRLF line terminators when they are present. Neither requires changing anything to find out.
Why does Git show my whole file as changed?
Because every line ends differently from the version stored, so every line reads as modified. It is a conversion rather than an edit. Setting the line ending behaviour for the repository stops it happening again, though the commit that caused it still shows as a rewrite.
Sources
Where the figures and behaviour described above were checked.
- Newline Wikipedia
- Internet Message Format IETF, RFC 5322
- Carriage return Wikipedia