Jenkins Error: 'hudson.plugins.git.GitException: Command "git fetch --tags --force --progress -- origin" returned status code 128' — Cause, Fix, and Troubleshooting Guide
Fix hudson.plugins.git.GitException: Command git fetch returned status code 128 in Jenkins — diagnose auth, refs, shallow clone, LFS, and network causes.
- #jenkins
- #ci-cd
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
The Jenkins Git plugin runs git fetch under the hood during the SCM checkout step. When the underlying git process exits non-zero, the plugin wraps the exit code in a GitException and fails the build. Status code 128 is Git’s generic “fatal” exit — the plugin can’t tell you why Git failed, only that it did.
hudson.plugins.git.GitException: Command "git fetch --tags --force --progress -- origin +refs/heads/*:refs/remotes/origin/*" returned status code 128:
stdout:
stderr: fatal: Authentication failed for 'https://git.example.com/team/app.git/'
The real cause is in the stderr: line, not the status code. The most common culprits are authentication, a missing or wrong ref/branch, a stale shallow clone, network/DNS failure, or LFS/submodule fetch problems. Always read the stderr before changing anything.
Symptoms
- Build fails at the “Checkout SCM” / “Declarative: Checkout SCM” stage before any of your pipeline steps run.
- Console log shows
returned status code 128with afatal:message instderr. - Manual
git clonefrom your workstation works, but Jenkins fails — pointing at credentials or the agent environment. - Intermittent 128s on large repos, often mentioning
shallow,RPC failed,early EOF, orremote end hung up. - After a force-push or branch delete, checkout of a previously valid commit/ref starts failing.
Common Root Causes
- Authentication failure —
fatal: Authentication failedorcould not read Username. The credential is missing, revoked, expired (PAT/deploy key), or the wrong credential ID is bound to the SCM config. - Host key verification failure (SSH) — the agent has never trusted the Git host, so SSH aborts. This surfaces as a distinct message; see the related guide.
- Wrong or deleted ref/branch —
couldn't find remote reforCouldn't find any revision to build. The branch was renamed/deleted, or a pipeline parameter points at a non-existent ref. - Broken shallow clone / bad object — a partial or corrupted
.gitin a reused workspace:fatal: the remote end hung up unexpectedlyordid not receive expected object. - Network, proxy, or DNS failure — the agent can’t reach the Git host:
Could not resolve host,Connection timed out, or a corporate proxy blocking443. - Git LFS not installed / not authenticated —
git-lfs filter-process: git-lfs: command not foundor an LFS smudge auth failure during fetch. - Submodule fetch failure — the parent fetch succeeds but a submodule URL is unreachable or uses different credentials.
- HTTP buffer / large object limits —
RPC failed; curl 56orearly EOFon very large fetches over HTTPS.
How to diagnose
Start by reading the exact stderr in the Jenkins console log — it names the failure class. Then reproduce and add tracing.
Enable Git trace on the agent to see the full transport-level conversation. In a pipeline, set the environment for the checkout:
pipeline {
agent any
environment {
GIT_TRACE = '1'
GIT_TRACE_PACKET = '1'
GIT_CURL_VERBOSE = '1' // HTTPS transport detail
}
stages {
stage('Checkout') {
steps { checkout scm }
}
}
}
Confirm what Jenkins actually runs. Manage Jenkins → System Log and the build console show the full git fetch command line, including the refspec. Verify the branch/refspec matches a ref that still exists:
# Run on the agent as the Jenkins user, using the same credentials:
git ls-remote --heads --tags https://git.example.com/team/app.git
# SSH remotes — prove the agent can authenticate and the host key is trusted:
ssh -T git@git.example.com
Check the agent’s Git and tooling:
git --version # plugin needs a reasonably modern git
git lfs version || echo "LFS not installed"
env | grep -i proxy # http_proxy / https_proxy / no_proxy
nslookup git.example.com # DNS resolution from the agent
If it only fails inside a reused workspace, the local .git is likely corrupt — inspect it:
cd /var/jenkins_home/workspace/app
git fsck --full || true
git rev-parse HEAD
Fixes
1. Fix credentials binding
Confirm the SCM configuration references a valid credential ID. In the job or pipeline, bind the correct one explicitly rather than relying on inheritance:
checkout([
$class: 'GitSCM',
branches: [[name: '*/main']],
userRemoteConfigs: [[
url: 'https://git.example.com/team/app.git',
credentialsId: '<credentials-id>' // must exist in Jenkins credential store
]]
])
For HTTPS, use a Personal Access Token as the password (many hosts no longer accept account passwords). For SSH, store a valid private key and ensure the matching deploy key is registered on the repo. Rotate expired tokens.
2. Trust the host key (SSH)
If stderr says Host key verification failed, add the host to the agent’s known_hosts or use the Git Host Key Verification strategy in Manage Jenkins → Security → Git Host Key Verification Configuration. Full walkthrough in the related guide below.
3. Force a clean, non-shallow checkout when the workspace is corrupt
Add the CleanBeforeCheckout and CloneOption extensions so a bad workspace is discarded and Git doesn’t choke on a broken shallow history:
checkout([
$class: 'GitSCM',
branches: [[name: '*/main']],
extensions: [
[$class: 'CleanBeforeCheckout'],
[$class: 'CloneOption', shallow: false, noTags: false, timeout: 30]
],
userRemoteConfigs: [[url: 'https://git.example.com/team/app.git',
credentialsId: '<credentials-id>']]
])
If you need shallow for speed on a big repo, set a sane depth and raise the timeout instead of disabling shallow entirely:
[$class: 'CloneOption', shallow: true, depth: 20, timeout: 30]
4. Point at a ref that exists
If stderr says couldn't find remote ref, correct the branch spec or parameter. Guard parameterized checkouts so a typo fails loudly:
script {
def exists = sh(returnStatus: true,
script: "git ls-remote --exit-code --heads origin ${params.BRANCH}") == 0
if (!exists) { error "Branch '${params.BRANCH}' does not exist on origin" }
}
5. Install and configure Git LFS on the agent
Install git-lfs on every agent that checks out an LFS repo, then let the plugin handle LFS via the GitLFSPull extension:
extensions: [[$class: 'GitLFSPull']]
Verify with git lfs env on the agent. Ensure the LFS endpoint credentials match the Git credentials.
6. Fix network / large-fetch failures
For RPC failed / early EOF on big HTTPS fetches, raise the HTTP post buffer on the agent’s Git config:
git config --global http.postBuffer 524288000 # 500 MB
For proxy environments, set http_proxy/https_proxy/no_proxy in the agent’s environment (Node → Configure → Environment variables) so Git uses the proxy. Confirm DNS and firewall rules allow the agent to reach the Git host on 443/22.
What to watch out for
- Always read
stderr, not the128. The status code is generic; the fatal line is the real error. - Pin Git and
git-lfsversions across agents. A checkout that works on one agent and 128s on another is usually a tooling orknown_hostsdifference. - Prefer credential IDs over embedding tokens in URLs — tokens in the SCM URL leak into console logs.
- Reused workspaces accumulate corruption. Add
CleanBeforeCheckouton flaky jobs rather than debugging stale.gitstate repeatedly. - Set an explicit checkout
timeoutso slow fetches fail with a clear message instead of hanging an executor. - Repeated 128s that mention retries may escalate into the
maximum-checkout-retry-attempts-reachedfailure — the underlying cause is the same fetch problem.
Related
- Jenkins Error: Host key verification failed — trust the Git host key so SSH checkouts stop aborting.
- Jenkins Error: Maximum checkout retry attempts reached — what happens when the same failing fetch is retried until Jenkins gives up.
- GitLab SSH: Permission denied (publickey) — the equivalent SSH checkout auth failure on GitLab CI.
More Jenkins prompts & error guides
Every Jenkins AI prompt and troubleshooting guide, in one place.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.