The 'error: invalid path' message occurs when Git tries to checkout files with names reserved by Windows, such as CON, PRN, AUX, or NUL. Rename the problematic files on a non-Windows system or use sparse checkout to skip them.
The "error: invalid path" error in Git occurs when you try to clone or checkout a repository that contains files or directories with names reserved by the Windows operating system. Windows reserves certain filenames for legacy device purposes, and it physically cannot create files with these names on NTFS file systems. The reserved names include: CON, PRN, AUX, NUL, COM1 through COM9, and LPT1 through LPT9. This restriction also applies when these reserved names have file extensions (e.g., `con.h`, `aux.txt`, `nul.conf`). The restriction is case-insensitive, so `Con`, `CON`, and `con` are all prohibited. When you attempt a `git clone` or `git checkout` on Windows and the repository contains such files, Git's NTFS protection mechanism blocks the operation. The clone may succeed, but the checkout fails because Windows cannot create the file. This commonly happens when cloning repositories that were created on Linux or macOS, where these filenames are perfectly valid.
First, look at the error message to identify which files are causing the issue:
error: invalid path 'path/to/con.h'
fatal: unable to checkout working tree
warning: Clone succeeded, but checkout failed.Common reserved names that cause this error:
- CON - Console device
- PRN - Printer device
- AUX - Auxiliary device
- NUL - Null device
- COM1 through COM9 - Serial ports
- LPT1 through LPT9 - Parallel ports
Note that con.h, aux.txt, nul.conf etc. are also invalid because the base name is reserved.
The cleanest solution is to rename the offending files from a Linux, macOS, or WSL environment:
# Clone on Linux/macOS/WSL where the files are valid
git clone https://github.com/user/repo.git
cd repo
# Find reserved filenames
find . -iname "con.*" -o -iname "prn.*" -o -iname "aux.*" -o -iname "nul.*" \
-o -iname "com[1-9].*" -o -iname "lpt[1-9].*"
# Rename the problematic files
git mv path/to/con.h path/to/console.h
git mv path/to/aux.txt path/to/auxiliary.txt
# Commit the changes
git commit -m "Rename Windows-reserved filenames for cross-platform compatibility"
git pushAfter pushing, Windows users can clone successfully.
If you're on Windows, use Windows Subsystem for Linux (WSL) to clone and work with the repository:
# Open WSL terminal
wsl
# Clone inside the WSL filesystem (not /mnt/c/)
cd ~
git clone https://github.com/user/repo.git
# Work with the files normally in WSL
cd repoImportant: Clone into the native WSL filesystem (~/), not into /mnt/c/ which maps to Windows and has the same restrictions.
You can disable Git's NTFS protection to allow checkout, but the problematic files will be skipped or created with zero bytes:
# Clone with NTFS protection disabled
git clone -c core.protectNTFS=false https://github.com/user/repo.git
# Or for an existing repo
git config core.protectNTFS false
git checkoutSecurity Warning: This setting was enabled by default to protect against CVE-2019-1353. Only use this temporarily and avoid setting it globally (--global). Files with reserved names will still be problematic - they may appear as zero-byte files or be skipped entirely.
If you don't need the files with reserved names, use sparse checkout to exclude them:
# Clone without checkout
git clone --no-checkout https://github.com/user/repo.git
cd repo
# Initialize sparse checkout
git sparse-checkout init --cone
# Set directories to include (exclude the problematic path)
git sparse-checkout set src/main src/tests docs
# Or exclude specific patterns
git sparse-checkout set '/*' '!path/to/problematic/'
# Now checkout
git checkoutThis lets you work with the repository while avoiding the incompatible files.
If you only need to read the files and don't need Git history, download the repository as a ZIP:
1. Go to the repository on GitHub/GitLab/Bitbucket
2. Click Code > Download ZIP
3. Extract the archive (Windows may skip or warn about reserved filenames)
This bypasses Git entirely but loses version control capabilities. Use this only for quick access to code you need to read but not modify.
If files were created with zero bytes due to the NTFS protection workaround, recover the content:
# Check if the file in Git has content
git show HEAD:path/to/con.h
# Create a patch with the content
git diff --binary HEAD~1 HEAD -- path/to/con.h > fix.patch
# Manually extract the content (on a non-Windows system)
# Then rename and commit as shown in step 2The original content is safely stored in Git's object database; only the working directory checkout fails.
### Why Windows Reserves These Names
These names date back to MS-DOS and represent device files. For example:
- CON represents the console (keyboard input/screen output)
- NUL is equivalent to /dev/null on Unix
- PRN and LPT1-9 represent printer devices
- COM1-9 represent serial port devices
Windows maintains backward compatibility with these names, making them permanently unavailable for regular files on NTFS.
### The Security Concern (CVE-2019-1353)
Git's core.protectNTFS setting was enabled by default to protect against a vulnerability where maliciously crafted repositories could exploit NTFS handling to write to unexpected locations in the .git directory. Disabling this protection opens you to potential attacks from untrusted repositories.
### Checking for Reserved Names Before Committing
Add a pre-commit hook to prevent accidentally adding Windows-reserved names:
#!/bin/bash
# .git/hooks/pre-commit
# Check for Windows reserved names
reserved_names=$(git diff --cached --name-only | grep -iE '(^|/)(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|$)')
if [ -n "$reserved_names" ]; then
echo "Error: Found Windows-reserved filenames:"
echo "$reserved_names"
echo "Please rename these files before committing."
exit 1
fi### CI/CD Considerations
If your CI/CD pipeline runs on Windows, ensure your repository doesn't contain reserved names:
# GitHub Actions example - fail early if reserved names exist
- name: Check for Windows-reserved filenames
run: |
reserved=$(find . -iregex '.*/\(con\|prn\|aux\|nul\|com[1-9]\|lpt[1-9]\)\(\.[^/]*\)?$' 2>/dev/null)
if [ -n "$reserved" ]; then
echo "Found Windows-reserved filenames:"
echo "$reserved"
exit 1
fi### Related Invalid Characters
Beyond reserved names, Windows also prohibits these characters in filenames:
- < > : " / \ | ? *
- Filenames ending with a space or period
- Control characters (ASCII 0-31)
Git will also report "error: invalid path" for files containing these characters.
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git