This error occurs when Git cannot find the git-upload-pack executable on the remote server during clone, fetch, or pull operations. It typically indicates a PATH configuration issue with non-interactive SSH sessions.
The git-upload-pack error occurs when your local Git client attempts to communicate with a remote repository over SSH, but the remote server cannot locate the git-upload-pack executable. This command is a critical component of Git's network protocol - it runs on the server side during fetch and clone operations to send repository data to the client. The root cause is almost always a PATH environment variable issue. When you connect to a remote server via SSH to run Git commands, the SSH daemon launches a non-interactive shell that has a different environment than a normal login shell. If Git is installed in a non-standard location (like /usr/local/git/bin or /opt/git/bin), the non-interactive shell's PATH may not include that directory, causing the git-upload-pack command to be unavailable. This issue is particularly common on macOS servers where Git is installed via Homebrew or custom installations, and on Linux servers where Git is compiled from source or installed in non-standard locations. It can affect any Git operation that reads from a remote repository, including git clone, git fetch, git pull, and git submodule update.
First, confirm that Git is installed on the remote server and locate the git-upload-pack executable:
ssh user@remote-server which git-upload-packIf this returns a path (like /usr/bin/git-upload-pack or /usr/local/git/bin/git-upload-pack), Git is installed. If it returns nothing or "command not found", Git needs to be installed on the remote server.
You can also check the PATH seen by non-interactive SSH sessions:
ssh user@remote-server echo \/home/jonas/.local/bin:/home/jonas/.vscode-server/bin/bf9252a2fb45be6893dd8870c0bf37e2e1766d61/bin/remote-cli:/home/jonas/.local/bin:/home/jonas/.local/bin:/home/jonas/.nvm/versions/node/v24.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/Python313/Scripts/:/mnt/c/Python313/:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/:/mnt/c/WINDOWS/System32/OpenSSH/:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/mnt/c/Program Files/NVIDIA Corporation/NVIDIA app/NvDLISR:/mnt/c/Program Files/dotnet/:/mnt/c/Program Files/PuTTY/:/mnt/c/Program Files/nodejs/:/mnt/c/ProgramData/chocolatey/bin:/mnt/c/Program Files/Git/cmd:/mnt/c/Users/Jonas/AppData/Local/Programs/Python/Python312/Scripts/:/mnt/c/Users/Jonas/AppData/Local/Programs/Python/Python312/:/mnt/c/Users/Jonas/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/Jonas/AppData/Local/Programs/Microsoft VS Code/bin:/mnt/c/Users/Jonas/AppData/Roaming/npm:/snap/bin:/home/jonas/.local/bin:/home/jonas/.local/bin:/home/jonas/.local/binCompare this to your interactive shell PATH to identify missing directories.
If you know where git-upload-pack is located on the remote server, specify it explicitly in your Git command:
# For clone operations
git clone --upload-pack /usr/local/bin/git-upload-pack user@remote:repo.git
# For fetch operations
git fetch --upload-pack /usr/local/bin/git-upload-packThis bypasses the PATH issue by telling Git exactly where to find the command.
To avoid specifying the path every time, configure it in your repository's Git config:
# Configure for a specific remote (usually origin)
git config remote.origin.uploadpack /usr/local/bin/git-upload-pack
git config remote.origin.receivepack /usr/local/bin/git-receive-pack
# Verify the configuration
git config --get remote.origin.uploadpackNow all future fetch and pull operations will use the specified path automatically.
On the remote server, ensure that .bashrc (not just .bash_profile) exports the correct PATH for non-interactive shells:
# SSH to the remote server
ssh user@remote-server
# Edit .bashrc
vi ~/.bashrc
# Add or modify PATH to include Git location
export PATH=/home/jonas/.local/bin:/home/jonas/.vscode-server/bin/bf9252a2fb45be6893dd8870c0bf37e2e1766d61/bin/remote-cli:/home/jonas/.local/bin:/home/jonas/.local/bin:/home/jonas/.nvm/versions/node/v24.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/mnt/c/Python313/Scripts/:/mnt/c/Python313/:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/:/mnt/c/WINDOWS/System32/OpenSSH/:/mnt/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/mnt/c/Program Files/NVIDIA Corporation/NVIDIA app/NvDLISR:/mnt/c/Program Files/dotnet/:/mnt/c/Program Files/PuTTY/:/mnt/c/Program Files/nodejs/:/mnt/c/ProgramData/chocolatey/bin:/mnt/c/Program Files/Git/cmd:/mnt/c/Users/Jonas/AppData/Local/Programs/Python/Python312/Scripts/:/mnt/c/Users/Jonas/AppData/Local/Programs/Python/Python312/:/mnt/c/Users/Jonas/AppData/Local/Microsoft/WindowsApps:/mnt/c/Users/Jonas/AppData/Local/Programs/Microsoft VS Code/bin:/mnt/c/Users/Jonas/AppData/Roaming/npm:/snap/bin:/home/jonas/.local/bin:/home/jonas/.local/bin:/home/jonas/.local/bin:/usr/local/git/bin
# Ensure .bashrc is sourced for non-interactive shells
# Add this to .bash_profile if needed:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fiTest the fix by running the diagnostic SSH command again:
ssh user@remote-server which git-upload-packFor a system-wide fix on the remote server, you can configure SSH to preserve PATH environment variables. This requires root access.
Edit /etc/ssh/sshd_config on the remote server:
sudo vi /etc/ssh/sshd_config
# Add or uncomment this line:
PermitUserEnvironment yesThen create ~/.ssh/environment file for the user:
# Create the environment file
vi ~/.ssh/environment
# Add the PATH:
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/binRestart the SSH daemon:
sudo systemctl restart sshd
# or on older systems:
sudo service sshd restartNote: Enabling PermitUserEnvironment has security implications and may not be allowed by your organization's policies.
The distinction between interactive and non-interactive shells is crucial to understanding this error. When you SSH into a server with a terminal (ssh user@server), it creates a login shell that executes .bash_profile or .profile. However, when Git connects over SSH to run git-upload-pack, it creates a non-interactive shell that only sources .bashrc. On macOS, Git installations via Homebrew or official DMG typically install to /usr/local/git/bin, which is not in the default system PATH compiled into sshd for security reasons.
For Git hosting platforms like Gitolite, Gitea, or custom Git servers, the git user often has a restricted shell. In these cases, ensure the PATH is set in the git user's shell initialization files or use the --upload-pack flag approach.
If you're using Git submodules, this error can occur when the superproject and submodule use different remote server configurations. Ensure all submodules have the uploadpack path configured if needed.
Some organizations use Git protocol wrappers or proxies that may require additional configuration beyond standard PATH fixes.
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