Troubleshooting ‘Git error pack-objects died of signal 13 pipe break’ on Alpine Linux for Large Pushes
Resolve 'pack-objects died of signal 13 pipe break' during large Git pushes on Alpine Linux. This guide details causes like memory exhaustion and ulimits, offering step-by-step fixes.
Resolve 'pack-objects died of signal 13 pipe break' during large Git pushes on Alpine Linux. This guide details causes like memory exhaustion and ulimits, offering step-by-step fixes.
Introduction
Encountering a "Git error pack-objects died of signal 13 pipe break" during a large git push operation can be a frustrating experience, particularly on resource-constrained environments like Alpine Linux. This error signals a critical failure on the remote Git server, where the pack-objects process — responsible for compressing Git objects into an efficient packfile — terminates unexpectedly. The client, still attempting to write data, receives a SIGPIPE (signal 13), indicating that the pipe it's writing to has been closed by the reading end. This guide provides a deep dive into the root causes and offers a robust, step-by-step resolution tailored for Alpine Linux and common hosting environments.
Symptom & Error Signature
Users typically observe this error on their local terminal during a git push command, especially when pushing a large number of new objects, a substantial new branch, or a repository with significant history changes.
Client-Side Error Output:
$ git push origin main
Enumerating objects: 123456, done.
Counting objects: 100% (123456/123456), done.
Delta compression using up to 8 threads
Compressing objects: 100% (123450/123450), done.
Writing objects: 100% (123456/123456), 2.30 GiB | 10.00 MiB/s, done.
Total 123456 (delta 98765), reused 0 (delta 0), pack-reused 0
error: pack-objects died of signal 13
error: remote unpack failed: unpack-objects died with exit code 13
To ssh://your-git-server.com/repo.git
! [remote rejected] main -> main (pack-objects died)
error: failed to push some refs to 'ssh://your-git-server.com/repo.git'
Potential Server-Side Logs (e.g., in /var/log/messages, Docker logs, or journalctl):
While SIGPIPE is a client-side symptom, the root cause lies on the server. Server-side logs might reveal the actual termination reason for pack-objects:
kernel: [pid] Out of memory: Kill process [pid] (git) score [score] or sacrifice child
kernel: Killed process [pid] (git-pack-obje) total-vm:[KB]KB, anon-rss:[KB]KB, file-rss:[KB]KB, shmem-rss:[KB]KB
or
git-receive-pack: failed to write to stdout, errno=28 (No space left on device)
or for systemd units:
systemd[1]: git-receive-pack.service: Main process exited, code=killed, status=13/PIPE
Root Cause Analysis
The "pack-objects died of signal 13 pipe break" error primarily indicates that the Git pack-objects process on the remote server terminated prematurely while the client was still sending data. The SIGPIPE signal on the client is a direct consequence of the server-side process closing its end of the communication pipe. The most common underlying causes, especially on Alpine Linux known for its minimal footprint, are:
Memory Exhaustion (Out-of-Memory Killer – OOM):
- The
pack-objectsprocess can be very memory-intensive when dealing with large repositories, many objects, or significant delta compression. - Alpine Linux, often used in Docker containers or low-resource VMs, frequently has aggressive memory limits or simply less available RAM.
- When
pack-objectsexceeds available memory or configured memory limits, the kernel's OOM killer steps in, terminating the process to prevent system instability. This is the most frequent cause ofSIGPIPEduring large pushes.
- The
Insufficient Disk Space:
- The
pack-objectsprocess needs temporary disk space to create packfiles before they are moved into the repository'sobjects/packdirectory. - If the server's disk, or the partition hosting the Git repository, runs out of space,
pack-objectscannot complete its operation and exits, leading to a pipe break.
- The
Process Limits (
ulimits):- Operating systems impose limits on processes, such as the number of open file descriptors (
LimitNOFILE), the number of processes (LimitNPROC), or stack size (LimitSTACK). - For very large repositories with deep histories,
pack-objectsmight internally open many files or spawn child processes. If it hits anulimit(e.g., maximum open files), it can crash. This is particularly relevant in minimal environments or tightly configuredsystemdservices or Docker containers.
- Operating systems impose limits on processes, such as the number of open file descriptors (
Network Timeouts/Instability (Less Common for SIGPIPE):
- While
SIGPIPEis generally a local process issue, an underlying network timeout or instability might cause the SSH session or HTTP connection to drop, which could lead to the server-side Git processes terminating prematurely. However, this usually manifests as different error codes or connection resets. For HTTP Git, web server (e.g., Nginx) or application server (e.g., Gunicorn, uWSGI) timeouts can also play a role.
- While
Corrupted Repository:
- A rare but possible cause is a corrupted Git repository on the server.
pack-objectsmight encounter an inconsistent object or packfile, leading to a crash.
- A rare but possible cause is a corrupted Git repository on the server.
Step-by-Step Resolution
This section outlines how to diagnose and resolve the pack-objects died of signal 13 error. We'll focus on common hosting practices, including Alpine-specific considerations where relevant, and general Linux system administration.
1. Server Resource Assessment (Disk Space & Memory)
Before making any configuration changes, verify that your server has adequate resources.
Check Disk Space: Connect to your Alpine Linux server via SSH and check disk utilization, especially for the partition hosting your Git repositories.
df -hLook for high usage (e.g., > 90%) on
/(root),/var, or the specific mount point where your Git repositories reside. If disk space is critically low, free up space or expand the filesystem.Check Memory Usage: Review the server's current memory consumption.
free -h cat /proc/meminfo | grep MemTotalIf available memory is consistently low, or if the
gitprocess itself is observed consuming a large portion of RAM before crashing (you might need to usehtoportopduring a push attempt), then memory exhaustion is likely the culprit.
2. Increase Server Memory Limits
This is often the most effective solution for SIGPIPE related to pack-objects. The approach depends on how your Git server is deployed.
a. For Git over SSH (Standalone Server/VM)
If Git is accessed via SSH, the sshd daemon might be constrained, or the system itself is running low on memory.
System-wide Memory: Consider increasing the RAM allocated to your VM or physical server if it's consistently running low.
SSH Daemon Limits (less common for direct OOM, but good practice): While Alpine's
sshdtypically uses OpenRC or is standalone,systemdenvironments (like Ubuntu/Debian) allow setting limits for services.If your Git server runs within a
systemdservice unit (e.g., a custom Git daemon or Git web service), you can define memory limits there. Forsystemdon Ubuntu/Debian:# Example: /etc/systemd/system/your-git-service.service.d/limits.conf [Service] MemoryLimit=2G # Or higher, e.g., 4G. Adjust based on your server's total RAM.Then reload and restart the service:
sudo systemctl daemon-reload sudo systemctl restart your-git-service.service
b. For Git in Docker Containers (Alpine within Docker)
If your Git server (e.g., Gitea, GitLab, or a bare Git repository served via SSH/HTTP) runs inside a Docker container based on Alpine Linux, you must adjust the container's resource limits.
# When running the container:
docker run -d
--name git_server
--memory="4g" # Allocate 4GB of RAM
--memory-swap="8g" # Allow 8GB of swap (if available on host)
--memory-swappiness="0" # Prefer not to swap (reduces I/O if possible)
your_alpine_git_image:latest
If using Docker Compose, update your
docker-compose.yml:version: '3.8' services: git_server: image: your_alpine_git_image:latest container_name: git_server deploy: resources: limits: memory: 4g # Set memory limit to 4GB reservations: memory: 2g # Reserve at least 2GBAfter modifying, run
docker-compose up -d --force-recreate.
c. For Git over HTTP (Nginx + Git Smart HTTP)
If you're serving Git over HTTP/HTTPS using Nginx and a backend like git-http-backend (CGI/FastCGI) or a dedicated Git application (like Gitea, GitLab), also check these:
PHP-FPM (if using PHP-based Git web frontends): Increase
memory_limitinphp.ini.# Example: /etc/php8/php.ini (for Alpine), or /etc/php/<version>/fpm/php.ini (Ubuntu/Debian) memory_limit = 512M # Or 1G, 2G. Adjust as needed.Restart PHP-FPM service:
# On Alpine (OpenRC) rc-service php-fpm8 restart # On Ubuntu/Debian (Systemd) sudo systemctl restart php8.2-fpm.service # Adjust versionNginx Client Max Body Size: While
pack-objectsis internal, large HTTP pushes can also fail if Nginx prematurely closes the connection. Ensure Nginx allows large body sizes.# Example: In http block, server block, or location block client_max_body_size 0; # Allows unlimited body size client_body_buffer_size 128k;Reload Nginx configuration:
sudo nginx -t && sudo systemctl reload nginx # For Systemd systems # On Alpine (OpenRC) sudo nginx -t && rc-service nginx reload
3. Adjust Process ulimits (Open Files, Processes)
Git operations, especially on large repositories, can hit default operating system limits for open files or processes.
a. System-wide ulimits (via /etc/security/limits.conf)
For bare-metal Alpine or VMs, edit /etc/security/limits.conf. This method requires PAM (Pluggable Authentication Modules) to be active for SSH logins, which is common.
# Example: /etc/security/limits.conf
# <domain> <type> <item> <value>
* soft nofile 65536
* hard nofile 65536
* soft nproc 4096
* hard nproc 4096
Log out and log back in to apply these limits for new sessions.
On minimal Alpine installations, PAM might not be fully configured to process
limits.conffor all services. If this doesn't work, considersystemdunit limits or Docker--ulimit.
b. systemd Service Unit Limits
If your Git service (e.g., an SSH server configured to restrict users, or a custom Git daemon) is managed by systemd (common on Ubuntu/Debian, less so by default on Alpine but possible if installed), you can set limits directly in its service unit file.
# Example: /etc/systemd/system/sshd.service.d/limits.conf (or your custom service)
[Service]
LimitNOFILE=65536
LimitNPROC=4096
Reload systemd and restart the service:
sudo systemctl daemon-reload
sudo systemctl restart sshd.service # Or your Git service
c. Docker Container ulimits
For Git servers running in Docker containers, explicitly set ulimits using the --ulimit flag during docker run or in docker-compose.yml.
# Docker run example:
docker run -d
--name git_server
--ulimit nofile=65536:65536 # soft:hard limit for open files
--ulimit nproc=4096:4096 # soft:hard limit for processes
your_alpine_git_image:latest
For Docker Compose:
version: '3.8' services: git_server: image: your_alpine_git_image:latest container_name: git_server ulimits: nofile: soft: 65536 hard: 65536 nproc: soft: 4096 hard: 4096After modifying, run
docker-compose up -d --force-recreate.
4. Optimize Git Repository (Server-Side)
Sometimes, the repository itself can become inefficient, causing pack-objects to work harder.
Run
git gc: Perform garbage collection on the remote repository. This optimizes the repository by packing loose objects and removing old packfiles.Connect to your server, navigate to the bare Git repository (e.g.,
/srv/git/repo.git), and run:cd /srv/git/repo.git git gc --prune=nowThis can be a memory-intensive operation itself, so ensure resources are available before running it.
Git Server Configuration: While less common, certain Git configurations on the server can impact
pack-objects.cd /srv/git/repo.git git config pack.windowMemory "256m" # Increase window memory if needed git config pack.SizeLimit "4g" # Limit packfile size, might make more smaller packfiles
5. Network & Timeout Considerations (for HTTP Git)
While less direct for SIGPIPE, ensure your network infrastructure and HTTP server are not prematurely closing connections for large pushes.
SSH
ClientAliveInterval: For SSH Git, if the client connection is idle for too long (e.g., during a very slow compression phase), the SSH server might disconnect it.# Example: /etc/ssh/sshd_config ClientAliveInterval 300 # Sends null packets every 300 seconds (5 min) ClientAliveCountMax 3 # Allows 3 intervals without client response before disconnectingRestart
sshdafter changes:sudo systemctl restart sshd(Ubuntu/Debian) orrc-service sshd restart(Alpine).Nginx/Proxy Timeouts: For HTTP Git, ensure Nginx or any reverse proxy has generous timeout settings.
# Example: In http, server, or location block proxy_read_timeout 300s; proxy_send_timeout 300s; send_timeout 300s;
6. Client-Side Workarounds (Temporary or When Server Control is Limited)
If you cannot immediately modify the server, consider these client-side adjustments:
Split Large Pushes: If you're pushing a very large branch or many new commits, try to split it into smaller, more manageable pushes. This might involve pushing a few commits at a time or force-pushing smaller segments if your workflow allows.
Increase
http.postBuffer(for HTTP Git only): This client-side setting controls the buffer size Git uses for HTTP POST requests. Increasing it can help for large HTTP pushes.git config --global http.postBuffer 524288000 # 500 MB
7. Advanced Diagnostics: strace (Highly Technical)
If the problem persists and you have root access to the server, strace can provide granular insight into the system calls made by pack-objects right before it crashes.
Identify the Git Process: When a
git pushis initiated, on the server, ansshdor web server process will spawngit-receive-pack, which in turn spawnsgit-pack-objects. You need to attachstracetogit-receive-packor its childgit-pack-objects.Attach
strace:- Start a
git pushfrom your client. - Immediately on the server, find the
git-receive-packorgit-pack-objectsprocess ID (PID):ps aux | grep git-receive-pack ps aux | grep git-pack-objects - Attach
straceto it:
Replacesudo strace -fp <PID> -o /tmp/git_strace.log<PID>with the actual process ID. - Let the client
git pushfail. - Examine
/tmp/git_strace.logfor system call failures (e.g.,ENOMEMfor out-of-memory,EAGAINfor resource limits,EPIPEfor pipe errors) or the last few successful calls before termination. This log can pinpoint the exact system call that failed.
- Start a
stracecan be resource-intensive and generate very large log files. Use it carefully on production systems and remove log files after debugging.
By systematically working through these steps, you should be able to identify and resolve the underlying resource limitations or configuration issues causing the "Git error pack-objects died of signal 13 pipe break" on your Alpine Linux-based Git server.