Jenkins Build Failed How to Fix: The Complete Troubleshooting Guide for 2026
There’s nothing quite like that red indicator next to your Jenkins job. Whether it shows up at 2 AM or five minutes before a release, a failed Jenkins build has a way of ruining your day fast. The good news? After years of debugging pipelines across dozens of teams, I can tell you that almost every Jenkins failure falls into one of a handful of root causes—and once you learn the pattern, most fixes take under five minutes.
This guide walks through the most common (and some sneaky edge-case) reasons your Jenkins build is failing, with copy-paste-ready solutions, real error messages, and concrete prevention tips.
Understanding Why Jenkins Builds Fail
Before you start changing things, you need to actually read what Jenkins is telling you. The Console Output is your best friend—click the build number, then Console Output (or add /console to the build URL).
A typical failure will show one of these patterns:
- Exit code 1 — generic failure, usually a test or compile error
- Exit code 127 — command not found (PATH issue)
- Exit code 137 — process killed (OOM or timeout)
- Exit code 143 — process terminated by SIGTERM
java.lang.OutOfMemoryError— heap exhaustionERROR: Checkout failed— SCM/Git problem
Jenkins almost never fails silently. The error is there; you just have to know where to look and what the message actually means.
Step 1: Check the Build Environment First
This is where I see developers waste the most time. They jump straight into debugging tests when the real problem is that their Jenkins agent doesn’t have the right tool installed.
Verify Tool Versions Match Your Local Setup
A build that works on your machine but fails in Jenkins usually means a version mismatch. Open Manage Jenkins → Global Tool Configuration and check:
- JDK version
- Node.js / npm version
- Python interpreter
- Maven / Gradle wrapper
- Docker (if using containerized builds)
Compare these against your local environment:
java -version
node -v
python3 --version
mvn -v
docker --version
Lock Down Versions With a Tool Installer
Don’t rely on whatever’s preinstalled on the agent. Use the tool() step in your pipeline:
pipeline {
agent any
tools {
jdk 'Temurin-17.0.13'
maven 'Maven-3.9.9'
nodejs 'Node-22.12.0'
}
stages {
stage('Build') {
steps {
sh 'java -version'
sh 'mvn -B clean package'
}
}
}
}
This guarantees the exact version is installed and on the PATH for every build.
Step 2: Diagnose Dependency Resolution Failures
If your environment is correct, the next most common culprit is dependencies. Maven, Gradle, npm, pip—they all fail differently, but the symptoms are similar.
Maven: “Could not resolve dependencies”
A real error message you’ll see:
[ERROR] Failed to execute goal on project my-service:
Could not resolve dependencies for project com.example:my-service:jar:1.4.2:
Failed to collect dependencies at com.fasterxml.jackson.core:jackson-databind:jar:2.18.1:
Failed to read artifact descriptor for jackson-databind:jar:2.18.1:
Could not transfer artifact com.fasterxml.jackson.core:jackson-databind:pom:2.18.1
from/to central (https://repo.maven.apache.org/maven2): transfer failed
Fix options:
- Check network/proxy settings on the agent:
bash
curl -I https://repo.maven.apache.org/maven2/ - Clear the local Maven cache for the problematic artifact:
bash
rm -rf ~/.m2/repository/com/fasterxml/jackson - Configure a mirror in
~/.m2/settings.xml:
xml
<settings>
<mirrors>
<mirror>
<id>internal-nexus</id>
<mirrorOf>central</mirrorOf>
<url>https://nexus.mycompany.com/repository/maven-public/</url>
</mirror>
</mirrors>
</settings>
npm: “ERESOLVE unable to resolve dependency tree”
Common with strict peer dependencies in Node 18+:
npm ERR! ERESOLVE could not resolve
npm ERR! Conflicting peer dependency: react@18.3.1
Fix: either align versions, or use:
npm ci --legacy-peer-deps
Better yet, pin your package-lock.json and never run npm install in CI—always npm ci for reproducible installs.
Python: ModuleNotFoundError in Jenkins
If your tests pass locally but Jenkins says:
ModuleNotFoundError: No module named 'requests'
You’re almost certainly missing a virtualenv step:
stage('Test') {
steps {
sh '''
python3 -m venv .venv
. .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
pytest -v
'''
}
}
Step 3: Resolve Source Code Management (SCM) Issues
Git problems are extremely common, especially after credential rotations or branch renames.
“ERROR: Error fetching remote repo origin”
This usually means:
- Expired SSH key or personal access token
- Wrong branch name (typo, case sensitivity)
- Repository moved or renamed
- Jenkins SSH key lacks read permission
Debug command (run manually on the agent):
ssh -T git@github.com
git ls-remote https://github.com/your-org/your-repo.git
For HTTPS repos using a token, store credentials in Jenkins under Manage Jenkins → Credentials and reference them in your pipeline:
stage('Checkout') {
steps {
git branch: 'main',
credentialsId: 'github-app-token',
url: 'https://github.com/your-org/your-repo.git'
}
}
Merge Conflicts in Multibranch Pipelines
If Jenkins tries to merge a feature branch into main for testing and hits a conflict, you’ll see:
MergeConflictException: Automatic merge failed; fix conflicts and then commit the result.
Fix: rebase the feature branch against main locally before pushing:
git fetch origin
git rebase origin/main
# resolve conflicts
git push --force-with-lease
Step 4: Fix Java Heap and Out of Memory Errors
If your build logs contain:
java.lang.OutOfMemoryError: Java heap space
or:
java.lang.OutOfMemoryError: Metaspace
you need to increase the memory allocated to the JVM running the build.
For the Maven Build Itself
Pass memory flags directly:
MAVEN_OPTS="-Xmx4g -XX:MaxMetaspaceSize=1g" mvn clean install
Or set them globally in Manage Jenkins → Global Tool Configuration → Maven.
For the Jenkins Controller (if the OOM is in the master log)
Edit jenkins.xml (Windows) or your systemd unit file (Linux):
# /etc/systemd/system/jenkins.service.d/override.conf
[Service]
Environment="JAVA_OPTS=-Xmx8g -Xms4g -XX:+UseG1GC"
Then:
sudo systemctl daemon-reload
sudo systemctl restart jenkins
For Docker Builds
When running docker build, the build context or a RUN step can OOM. Bump the daemon:
{
"memory": "4g",
"swap": "2g"
}
Step 5: Clear a Corrupted Workspace
Sometimes there’s no obvious error—the build just refuses to pass after weeks of working fine. The workspace on the agent has gotten into a bad state.
Symptoms:
Stale file detectedPermission deniedon files you should own- Builds pass on a fresh agent but fail on the old one
Fix: wipe the workspace and rerun:
- Open the job in Jenkins
- Click Workspace in the sidebar
- Click Wipe Current Workspace
- Trigger a new build
Or do it in the pipeline:
stage('Clean') {
steps {
cleanWs()
}
}
I keep cleanWs() at the start of every non-cache-heavy pipeline. It eliminates an entire class of “works on Tuesday but not Wednesday” issues.
Step 6: Handle Permission and File Ownership Issues
If you see:
/usr/local/bin/mvn: Permission denied
or:
fatal: detected dubious ownership in repository
your Jenkins user doesn’t have proper access.
Fix File Ownership
sudo chown -R jenkins:jenkins /var/lib/jenkins/workspace/
sudo chmod -R u+rwX /var/lib/jenkins/workspace/
Fix Git “Dubious Ownership”
Newer Git versions are strict about who owns a repo. Add this to your pipeline:
git config --global --add safe.directory '*'
Or scope it to a single directory:
git config --global --add safe.directory /var/lib/jenkins/workspace/my-job
Step 7: Debug Pipeline Syntax Errors
Declarative pipeline syntax is unforgiving. A common failure:
WorkflowScript: 23: Expected a symbol @ line 23, column 9.
Use Snippet Generator (linked from any pipeline job page) instead of writing complex steps by hand. And always validate locally with:
curl -X POST -F "jenkinsfile=<Jenkinsfile" \
https://your-jenkins.example.com/pipeline-model-converter/validate
Common Pipeline Mistakes
| Problem | Symptom | Fix |
|---|---|---|
Missing agent directive |
Required: agent |
Add agent any at the top |
sh step on Windows agent |
Command not found |
Use bat instead |
| Missing double quotes around variables | Variable not expanded | Use "${VAR}" not '${VAR}' |
when condition referencing undefined env |
Skip unexpected branch | Define the env var first |
Step 8: Address Network, Proxy, and DNS Problems
Internal corporate networks love to break Jenkins builds in mysterious ways. Look for:
Caused by: java.net.UnknownHostException: repo.example.com
or:
javax.net.ssl.SSLHandshakeException: PKIX path building failed
Configure the JVM Proxy
JAVA_TOOL_OPTIONS="
-Dhttp.proxyHost=proxy.corp.lan
-Dhttp.proxyPort=8080
-Dhttps.proxyHost=proxy.corp.lan
-Dhttps.proxyPort=8080
-Dhttp.nonProxyHosts=localhost|127.0.0.1|*.corp.lan
"
Trust a Self-Signed Certificate
For internal Nexus or Artifactory:
sudo keytool -importcert \
-alias corp-nexus \
-file /etc/ssl/certs/corp-nexus.pem \
-keystore $JAVA_HOME/lib/security/cacerts \
-storepass changeit -noprompt
Step 9: Investigate Edge Cases That Drive People Crazy
These are the failures that take hours to track down because the error messages are misleading.
The Clock Skew Problem
If TLS handshakes fail intermittently or certain timestamp checks complain, the agent’s clock might be off:
timedatectl status
sudo chronyc -a makestep
Even a few seconds of skew can break signed artifact verification.
The “Invisible Character” Pipeline Bug
I once spent three hours on a pipeline that failed with a cryptic syntax error. The cause: a non-breaking space (\u00a0) pasted from a Confluence doc. If you see errors that don’t make sense, retype the offending line manually—don’t copy-paste.
Zombie Processes on Agents
Long-running agents accumulate zombie processes. If builds start timing out randomly:
ps aux | grep -E 'java|maven|gradle' | grep -v grep
sudo pkill -f 'maven'
sudo pkill -f 'gradle'
Then schedule a periodic cleanup cron on the agent.
Disk Space Exhaustion
Caused by: java.io.IOException: No space left on device
Check the agent:
df -h /var/lib/jenkins
du -sh /var/lib/jenkins/* | sort -rh | head
Old build artifacts are the usual culprit. Configure Discard Old Builds in job settings:
options {
buildDiscarder(logRotator(
numToKeepStr: '50',
artifactNumToKeepStr: '10'
))
}
Step 10: Make Builds Debuggable From the Start
Once your build is green again, take ten minutes to make the next failure faster to diagnose.
Enable Detailed Logging
sh '''
set -euxo pipefail
mvn -X clean install
'''
-X is Maven’s debug mode. For npm:
npm ci --loglevel verbose
Capture Build Metadata
post {
always {
archiveArtifacts artifacts: '**/target/*.jar', allowEmptyArchive: true
junit '**/target/surefire-reports/*.xml'
}
failure {
emailext subject: "Build failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "See ${env.BUILD_URL}",
to: 'team@mycompany.com'
}
}
Use timestamps and ansiColor
Install the Timestamps and AnsiColor plugins and wrap your pipeline:
options {
timestamps()
ansiColor('xterm')
}
Now you can see exactly when each step ran and read colorized output instead of escaped ANSI codes.
Prevention: Building a Resilient Jenkins Setup
The best fix is preventing failures in the first place. These practices have cut my Jenkins debugging time by an estimated 80% over the last two years.
Pin Everything
- Lock tool versions in Global Tool Configuration
- Use
.tool-versions(asdf) or.nvmrcfor language runtimes - Commit
package-lock.json,pom.xml, andbuild.gradlewith exact versions - Use container-based builds with a
Dockerfiledefining your toolchain
Use mvn -B (Batch Mode)
Without -B, Maven downloads progress bars spam logs and occasionally hang. Always use:
mvn -B -ntp clean install
-ntp disables transfer progress for cleaner output.
Run Linting in a Separate Early Stage
Fail fast on syntax/style issues before the expensive build:
stage('Lint') {
steps {
sh 'mvn -B -ntp checkstyle:check'
}
}
Use Parallel Test Execution
stage('Test') {
parallel {
stage('Unit') {
steps { sh 'mvn -B -ntp test' }
}
stage('Integration') {
steps { sh 'mvn -B -ntp failsafe:integration-test' }
}
}
}
Monitor Agent Health
A dead agent causes cascading failures. Set up health checks:
#!/bin/bash
# cron every 5 minutes
JENKINS_AGENT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://jenkins.example.com/computer/agent-1/api/json)
if [ "$JENKINS_AGENT_STATUS" != "200" ]; then
systemctl restart jenkins-agent
fi
Key Takeaways
- Always read Console Output first. Jenkins tells you exactly what failed; you just need to decode the message.
- Environment mismatches cause the majority of failures. Lock tool versions in
tools {}blocks. cleanWs()at the start of every pipeline eliminates a huge class of workspace corruption bugs.- Memory issues are easy to fix—just bump
-Xmxfor Maven or Jenkins JVM. - Pin dependencies and use
npm ci/mvn -Bfor reproducible builds. - Wipe the workspace when in doubt. It’s the Jenkins equivalent of “turn it off and on again.”
- Prevention is cheaper than debugging—invest in build metadata capture, parallel stages, and automated agent monitoring.
Frequently Asked Questions
Why does my Jenkins build fail but work locally?
The most common reasons are version mismatches (JDK, Node, Python), different environment variables, missing dependencies, or workspace corruption. Always compare tool versions between your machine and the Jenkins agent first.
How do I see why a Jenkins build failed?
Open the failed build, click Console Output in the sidebar, and scroll to the bottom. Look for lines starting with ERROR, FAILED, or Exception. The exit code (1, 127, 137, 143) also gives you a strong hint about the root cause.
What does exit code 137 mean in Jenkins?
Exit code 137 means the process was killed, typically because it ran out of memory (OOM killer) or exceeded a