1. Introduction

A Jenkins pipeline that hangs — showing "running" in the UI but producing no log output and never completing — is one of the most frustrating CI/CD problems. Unlike a clean failure with an error message, a stuck pipeline occupies an executor indefinitely, blocks other builds from running, and gives you nothing to work with except the knowledge that something is waiting for something else.

This guide covers the most common causes of stuck Jenkins pipelines and how to diagnose and fix each one. For general pipeline failures that do produce an error, see Fix CI/CD Pipeline Failed.

2. What "Stuck" Means for Jenkins

A Jenkins pipeline hangs when a step starts executing and never exits — either because it's waiting for external input, waiting for a resource that never becomes available, or executing a process that ignores termination signals. Jenkins keeps the executor reserved and the build in "running" state until the pipeline either completes, is aborted manually, or times out (if a timeout is configured).

3. Common Causes

4. Step-by-Step Diagnosis and Fix

Step 1: Identify where the pipeline is stuck

# In the Jenkins UI:
# 1. Click on the running build
# 2. Click "Pipeline Steps" (for Declarative pipelines)
# 3. The currently executing step is the one that's hung
# OR
# Click "Console Output" and see what the last log line was

# From the Jenkins agent host (if you have SSH access):
# Find the process that Jenkins is waiting for
ps aux | grep -E "npm|python|docker|kubectl|ssh" | grep -v grep

# Or find Jenkins agent processes specifically
ps aux | grep jenkins | grep -v grep

Step 2: Fix interactive prompts in scripts

The most common cause: a command waiting for y/n input that will never arrive in CI.

# Common commands that prompt for input — and their non-interactive flags:

# Package managers:
apt-get install -y package      # -y suppresses confirmation
yum install -y package
pip install --no-input package

# Terraform:
terraform apply -auto-approve
terraform destroy -auto-approve

# SSH (host key verification):
ssh -o StrictHostKeyChecking=no -o BatchMode=yes user@host command

# Docker (when running containers that ask for input):
echo "y" | docker exec -i container-name some-command
# or use: docker exec -i container-name sh -c "echo y | command"

Step 3: Add timeouts to all waiting commands

# kubectl rollout status ALWAYS needs a timeout
kubectl rollout status deployment/my-app --timeout=5m

# kubectl wait also needs a timeout
kubectl wait --for=condition=Available deployment/my-app --timeout=3m

# Wrap an entire stage in a Jenkins timeout:
stage('Deploy') {
    options {
        timeout(time: 10, unit: 'MINUTES')
    }
    steps {
        sh 'kubectl apply -f manifests/'
        sh 'kubectl rollout status deployment/my-app --timeout=8m'
    }
}

# Global pipeline timeout (catches anything that hangs):
pipeline {
    options {
        timeout(time: 1, unit: 'HOURS')
    }
    ...
}

Step 4: Fix stuck input steps

# A pipeline with an input step waiting indefinitely:
stage('Approve') {
    steps {
        input message: 'Deploy to production?', ok: 'Deploy'
    }
}

# Fix: wrap with a timeout so it auto-aborts if not approved
stage('Approve') {
    options {
        timeout(time: 30, unit: 'MINUTES')
    }
    steps {
        input message: 'Deploy to production?', ok: 'Deploy'
    }
}

# Or abort pending input from the Jenkins Script Console (Manage Jenkins → Script Console):
Jenkins.instance.getItemByFullName('my-pipeline')
    .getBuildByNumber(42)
    .getAction(org.jenkinsci.plugins.workflow.support.steps.input.InputAction.class)
    .getExecutions()
    .each { it.proceed('') }

Step 5: Kill a stuck build and its child processes

# In Jenkins UI: Build → Abort (stop icon)
# If that doesn't work after 30 seconds, kill from the agent:

# Find the PID of the stuck command (on the agent host)
ps aux | grep "my-hanging-command"

# Kill it
kill -9 <PID>

# Jenkins should then mark the build as aborted
# If Jenkins itself appears frozen, restart just the agent:
# Jenkins → Manage Jenkins → Manage Nodes → <node> → Disconnect/Reconnect

# Using Jenkins Script Console to abort a specific build:
Jenkins.instance.getItemByFullName('my-job').getBuildByNumber(42).doStop()

Step 6: Fix background processes that prevent build completion

# A script that starts a background process can prevent Jenkins from completing
# the build because it waits for all child processes to exit.

# Wrong: starts background process, Jenkins waits for it forever
sh 'nohup ./server.sh &'

# Fix: disown the process so Jenkins doesn't track it
sh 'nohup ./server.sh & disown'

# Or for integration tests: start, run tests, stop
sh '''
  ./server.sh &
  SERVER_PID=$!
  sleep 5  # wait for startup
  npm run test:integration
  kill $SERVER_PID
'''

5. Verification Steps

# After fixing, re-run the pipeline and monitor:
# 1. The previously-stuck stage should complete within its timeout
# 2. No executor should remain in "Running" state after the pipeline ends

# Check that no lingering processes are left on the agent
ps aux | grep -E "your-hanging-command" | grep -v grep
# Should return no results after the build completes

6. Common Mistakes

7. Prevention Tips

8. FAQ

The "Abort" button in the UI doesn't stop the build. Why?

The stuck process is ignoring SIGTERM. Jenkins sends SIGTERM to the build process when you abort, but some processes (particularly Java processes, Docker containers, or processes that trap signals) ignore it. You'll need to kill the process directly on the agent host using kill -9 <PID>, or kill the Docker container if the build runs in one.

How do I prevent stuck builds from blocking my executor pool?

Add a global timeout in every Jenkinsfile: options { timeout(time: 2, unit: 'HOURS') }. This ensures no build can hold an executor longer than 2 hours regardless of what's hanging. Also consider configuring the Jenkins "Build Discarder" plugin to auto-abort builds that exceed your maximum expected duration.

9. Summary

SymptomCauseFix
Pipeline hangs on shell commandInteractive prompt waiting for inputAdd -y, --yes, or --non-interactive flags
Hangs on kubectl rollout statusNo --timeout flagAdd --timeout=5m to the command
Hangs on input stepApproval request never answeredWrap with timeout(time: 30, unit: 'MINUTES')
Build completes in Jenkins but executor stays busyBackground process not disownedUse & disown or kill PID explicitly
Abort button doesn't workProcess ignoring SIGTERMkill -9 from agent host; kill Docker container

Explore More in This Category

Explore more in this category: CI/CD guides. Browse all DevOps Compass articles or jump to: Kubernetes, AWS, CI/CD, Containers, Monitoring, Networking.