---
title: Windows reserved device names break git (AUX, CON, PRN, NUL, COM, LPT)
title_en: Windows reserved device names break git (AUX, CON, PRN, NUL, COM, LPT)
description: Why a folder named `aux` makes `git add` fail with ENOENT on Windows even though `ls` and `Get-Content` see it, the DOS-era device-name rule behind it, and how to rename out of the trap.
sidebar_label: Windows reserved device names
---

# Windows reserved device names break git (AUX, CON, PRN, NUL, COM, LPT)

## TL;DR

Windows reserves a handful of file and folder names for DOS-era hardware devices. They **cannot be used as a file or folder name** anywhere in a path:

- `CON`, `PRN`, `AUX`, `NUL`
- `COM0`–`COM9`, `COM¹`, `COM²`, `COM³`
- `LPT0`–`LPT9`, `LPT¹`, `LPT²`, `LPT³`

The rule is **case-insensitive** (`aux` = `AUX` = `Aux`) and **applies even with an extension** (`aux.txt`, `nul.tar.gz` are also treated as the device).

It applies to **any segment** of the path — `public/aux/foo.svg` fails for the same reason as `aux/foo.svg`.

---

## Problem

In a Cangjie-practice project, 495 auxiliary glyph SVGs were downloaded into `public/aux/`, ready to `git add` and push.

### Symptoms

```
$ git add public/aux/Cjem-a0-1.svg
error: open("public/aux/Cjem-a0-1.svg"): No such file or directory
error: unable to index file 'public/aux/Cjem-a0-1.svg'
fatal: adding files failed
```

Yet the same file:

- `ls public/aux/Cjem-a0-1.svg` lists it with the correct size
- `Get-Content public/aux/Cjem-a0-1.svg` reads its contents
- `stat` reports all metadata as normal
- `git ls-files --others --exclude-standard public/aux/` enumerates it

**Copying the same file to `public/_test_dir/test.svg` makes `git add` succeed immediately.** So the problem is not the file — it is the directory name `aux`.

## Environment

- Windows 11
- Git for Windows (mingw-compiled `git.exe`)
- PowerShell 7+ and `cmd.exe`
- NTFS volume

## The clue that gave it away

Trying `Rename-Item public/aux public/aux_temp` produced:

```
Cannot rename the specified target, because it represents a path or device name.
```

The phrase "represents a path or device name" is the giveaway — Windows is treating `aux` as a device, not a folder.

## Solution

1. Rename via `cmd.exe` (PowerShell's `Rename-Item` refuses, but `cmd`'s `move` works):

   ```
   cmd /c "move public\aux public\auxiliary"
   ```

2. Update every reference in code: `<img src="aux/...">` → `<img src="auxiliary/...">`, `OUT_DIR = 'public/aux'` → `'public/auxiliary'`.
3. `git add` succeeds immediately afterwards.

## Root cause

A compatibility burden carried forward from MS-DOS. The OS reserved names for hardware devices (auxiliary device, console, printer, the null sink) so programs could "read and write devices as if they were files."

DOS-era example — sending text to the screen:

```
COPY my_text.txt CON
```

This "copies" the contents of `my_text.txt` to the `CON` (console) device.

To keep three-decade-old programs running, Windows preserves the rule. Even on Windows 11, `Get-Content > CON` in PowerShell still writes to the console.

### Why `ls` / `stat` / `Get-Content` see the folder but `git`'s `open()` does not

Two different syscall paths:

- **Directory enumeration** (`FindFirstFile` / `readdir`) lists actual NTFS entries, including a directory literally named `aux`. So `ls`, `stat`, and `git ls-files` all see it.
- **Opening by path** (`CreateFile` / POSIX `open`) makes Windows perform "DOS device name resolution" before touching disk. When it sees `aux`, it opens the device — never the directory of the same name on disk. So git's `open("public/aux/...")` receives `ENOENT`.

PowerShell's `Get-Content` goes through .NET, which in some versions automatically prefixes `\\?\` to bypass the resolver — so it reads the file fine. But `git.exe` is a mingw-compiled native program calling Win32 APIs directly, without that workaround.

---

## Trivia: `\\?\` prefix bypasses the rule

Windows APIs accept a `\\?\` path prefix that skips all DOS path parsing, including the device-name check.

```powershell
# Normal mkdir is blocked
mkdir aux
# Cannot create the specified target...

# With the \\?\ prefix it succeeds
[System.IO.Directory]::CreateDirectory('\\?\D:\test\aux')
```

**Do not actually do this.** The resulting `aux` folder cannot be opened in File Explorer or removed with `rm` / `Remove-Item` — only further `\\?\` calls can manipulate it. It is very easy to create something you cannot clean up.

If the word `aux` is semantically necessary, use a variant: `aux_`, `auxi`, `auxiliary`, `aux-shapes`.

---

## Checklist: filter before creating a new file or folder

In any cross-platform project, before committing to a directory or file name, verify:

- [ ] Not one of `CON / PRN / AUX / NUL`
- [ ] Not one of `COM0`–`COM9`
- [ ] Not one of `LPT0`–`LPT9`
- [ ] Not used as the base name with an extension (`aux.txt`, `nul.json` are also blocked)
- [ ] If sharing code with teammates: a name that works fine on Linux/macOS may explode on Windows

Anyone who hits this typically assumes their Git install is broken, the file is corrupt, or it is a permissions issue — and only finds the real cause after a long detour.

## References

- [Microsoft Docs — Naming Files, Paths, and Namespaces](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file)
- Full reserved list: `CON`, `PRN`, `AUX`, `NUL`, `COM0`–`COM9`, `LPT0`–`LPT9`
- `\\?\` prefix details: Microsoft Docs, "Maximum Path Length Limitation" section
