The 'fatal: cannot create pack: Too many open files' error occurs when Git exceeds the operating system's limit on the number of files a process can open simultaneously. This commonly happens during garbage collection, push, fetch, or repack operations on large repositories with many loose objects.
The "fatal: cannot create pack: Too many open files" error indicates that Git has hit the EMFILE (error: maximum files) limit imposed by the operating system. Every process on Unix-like systems has a limit on how many file descriptors it can hold open at once, controlled by the `ulimit -n` setting. Git operations like `git gc`, `git push`, `git fetch`, and `git repack` need to open many files simultaneously, especially when working with loose objects or multiple packfiles. By default, Linux systems allow 1024 open files per process, while macOS defaults to an even lower 256. When Git needs to process more objects than this limit allows, the operation fails with this error. The most common trigger is Git's automatic garbage collection (`git gc --auto`), which runs automatically during push and fetch operations. When a repository accumulates approximately 6,700 loose objects, Git attempts to pack them, requiring file handles for each object. If your ulimit is below this threshold, the garbage collection will fail.
First, check your current ulimit settings to understand the constraint:
# Check soft limit (current limit)
ulimit -n
# Check hard limit (maximum allowed)
ulimit -Hn
# View all limits
ulimit -aThe soft limit is what your processes actually use, while the hard limit is the maximum you can set without root privileges. On most Linux systems, you'll see 1024 as the default soft limit.
For an immediate fix, increase the limit in your current shell session:
# Increase to 8192 (common safe value)
ulimit -n 8192
# Or increase to 65536 for very large repositories
ulimit -n 65536
# Then retry your Git operation
git push origin mainNote: You can only increase up to the hard limit. If you need more, you'll need to modify system configuration files with root access.
To persist the change across sessions and reboots, edit the limits configuration:
# Edit the limits configuration file
sudo nano /etc/security/limits.conf
# Add these lines at the end (replace 'username' with your user or use '*' for all users)
username soft nofile 65536
username hard nofile 65536
# Or for all users:
* soft nofile 65536
* hard nofile 65536You may also need to ensure PAM is configured to apply these limits:
# Check if pam_limits is enabled
grep pam_limits /etc/pam.d/common-session
# If not present, add:
# session required pam_limits.soLog out and back in for changes to take effect.
If Git is running as a systemd service (like in CI/CD), configure limits in the service file:
# Edit or create a service override
sudo systemctl edit your-git-service
# Add these lines:
[Service]
LimitNOFILE=65536Or modify the system-wide systemd defaults:
# Edit systemd configuration
sudo nano /etc/systemd/system.conf
# Add or modify:
DefaultLimitNOFILE=65536
# Reload systemd
sudo systemctl daemon-reexecIf you cannot modify system limits, configure Git to run garbage collection before hitting the file limit:
# Lower the gc.auto threshold to trigger GC earlier
# Set to a value below your ulimit -n
git config --global gc.auto 200
# Or disable automatic garbage collection entirely
git config --global gc.auto 0With automatic GC disabled, you'll need to manually run garbage collection periodically:
# Run manual garbage collection
git gc
# Or more aggressive cleanup
git gc --aggressive --prune=nowIf the error has already occurred, manually clean up the repository:
# First, temporarily increase ulimit if possible
ulimit -n 8192
# Run garbage collection
git gc
# Or use git repack with specific options
git repack -a -d --depth=250 --window=250If you can't increase ulimit, try this workaround:
# Push your commits to remote
git push origin main
# Delete the local repository
cd ..
rm -rf your-repo
# Clone fresh (without loose objects)
git clone https://github.com/user/your-repo.gitFor large repositories, configure Git's pack settings to reduce resource usage:
# Limit memory used during packing (100MB)
git config --global pack.windowMemory "100m"
# Limit pack file size
git config --global pack.packSizeLimit "100m"
# Reduce threading to limit concurrent file access
git config --global pack.threads 1
# Reduce delta cache size
git config --global pack.deltaCacheSize "100m"These settings trade performance for lower resource usage, which can help avoid the file limit error.
macOS has a particularly low default limit (256). To fix:
# Check current limit
ulimit -n
# Temporarily increase (per session)
ulimit -n 4096
# Make permanent by adding to shell profile
echo 'ulimit -n 4096' >> ~/.zshrc
# Or for bash:
echo 'ulimit -n 4096' >> ~/.bash_profile
# Source the profile
source ~/.zshrcFor system-wide changes on modern macOS (10.10+):
# Create or edit launchd configuration
sudo nano /Library/LaunchDaemons/limit.maxfiles.plistAdd this content:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxfiles</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>65536</string>
<string>65536</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>Then load it:
sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plistDocker containers often have restricted limits. Configure them in your Docker setup:
# Run container with increased ulimit
docker run --ulimit nofile=65536:65536 your-image
# Or in docker-compose.yml:
services:
your-service:
ulimits:
nofile:
soft: 65536
hard: 65536For Kubernetes:
apiVersion: v1
kind: Pod
spec:
containers:
- name: git-container
securityContext:
# Note: requires privileged mode or proper security policies
resources:
limits:
# Some Kubernetes setups allow ulimit configurationYou may need to configure the underlying nodes or use init containers to set limits.
### Understanding File Descriptor Limits
Unix-like systems have two levels of file limits:
- Per-process limit (ulimit -n): Maximum files a single process can open. This is what Git hits.
- System-wide limit (fs.file-max): Total files all processes combined can open.
Check system-wide limit:
cat /proc/sys/fs/file-max
# Current usage
cat /proc/sys/fs/file-nrIf the system-wide limit is also low, increase it:
# Temporary
sudo sysctl -w fs.file-max=2097152
# Permanent (add to /etc/sysctl.conf)
fs.file-max = 2097152### Why 6,700 Objects Triggers the Error
Git's gc.auto defaults to 6700, meaning automatic garbage collection runs when loose objects exceed this count. During GC, Git needs to open file handles for:
- Each loose object being packed
- The new packfile being written
- Index files
- Temporary files
With overhead, processing 6,700 objects can require 7,000+ file handles, exceeding the default 1024 limit.
### Git Bash on Windows
Git Bash has its own ulimit constraints:
# Maximum on Git Bash is around 3200
ulimit -n 3200
# Note: Cannot lower limit once raised in same sessionFor Windows native Git (cmd/PowerShell), file limits work differently and are generally higher by default.
### Diagnosing with strace
To see exactly which files Git is trying to open:
strace -e open,openat -f git gc 2>&1 | tail -50This helps identify if Git is properly closing files or if there's a file descriptor leak.
### CI/CD Specific Considerations
Many CI systems run with reduced limits:
- GitHub Actions: Generally has high limits, but self-hosted runners may not
- GitLab CI: Configurable via runner settings
- Jenkins: Depends on how the agent is launched; configure in systemd service file
- CircleCI: May need resource_class adjustment
Always verify limits in CI:
# Example GitHub Actions step
- name: Check ulimit
run: ulimit -akex_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