Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Jenkins By James Joyner IV · · 9 min read

Jenkins Error: 'hudson.remoting.ChannelClosedException: Channel "unknown": Remote call ... failed. The channel is closing down or has closed down' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix Jenkins 'hudson.remoting.ChannelClosedException: the channel is closing down or has closed down': diagnose agent disconnects, OOM kills, and network drops.

  • #jenkins
  • #ci-cd
  • #troubleshooting
  • #errors
Free toolkit

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 remoting channel between the Jenkins controller and an agent has closed while a build was still trying to use it. Every command the controller sends to an agent — running a shell step, copying a file, reading a workspace — travels over this channel, so when it drops the build fails immediately with:

hudson.remoting.ChannelClosedException: Channel "unknown": Remote call to agent-01 failed. The channel is closing down or has closed down.
	at hudson.remoting.Channel.send(Channel.java:...)
	at hudson.remoting.Request.call(Request.java:...)
	at hudson.remoting.Channel.call(Channel.java:...)

This is almost never a bug in your pipeline logic — the connection to the agent went away. The real cause sits underneath: the agent JVM was killed, the network blipped, a firewall reset an idle connection, or the ping thread declared the agent dead. Diagnosis is about finding why the far end vanished.

Symptoms

  • A build fails mid-step with ChannelClosedException / “the channel is closing down or has closed down”.
  • The agent shows as offline (or briefly flaps offline then back) in Manage Jenkins → Nodes right after the failure.
  • The controller log records Ping failed. Terminating the channel or Connection was aborted.
  • Failures cluster on one flaky agent, one network segment, or on long/idle steps.
  • Inbound (JNLP) agents log Terminated or reconnect loops in their own console output.
  • The agent host shows an OOM kill, a service restart, or a node reboot around the failure time.

Common Root Causes

  • Agent JVM killed (OOM or crash) — the remoting process on the agent died (out of memory, kernel OOM-killer, host running the container was reclaimed), so the channel closed abruptly.
  • Network blip / connection reset — a transient loss between controller and agent, or a stateful firewall/load balancer that drops idle TCP connections, tears the channel down.
  • Ping thread timeout — the controller’s ping thread got no response within the timeout (agent under heavy GC or CPU starvation) and proactively terminated the channel.
  • Inbound (JNLP) agent disconnect — the reverse-proxy in front of the JNLP port dropped or timed out the WebSocket/TCP connection, or two agents shared one secret and fought over the slot.
  • Java version mismatch — controller and agent run incompatible Java versions, causing remoting handshake or serialization failures that close the channel.
  • Firewall / idle timeout — a stateful firewall between the two hosts silently expires the connection during a long, quiet step.

How to diagnose

Look at both ends. The controller side is in the service log; the agent side is on the node’s log page or the agent host itself.

Controller log — find whether it was a ping timeout or a hard close:

journalctl -u jenkins --since '30 min ago' \
  | grep -iE 'ChannelClosed|Ping failed|Terminating the channel|is offline|reconnect'

Check the agent’s own log page in the UI (Manage Jenkins → Nodes → agent-01 → Log) and, on the agent host, whether the JVM was OOM-killed or the service restarted:

# On the agent host
dmesg -T | grep -i 'killed process\|out of memory'
systemctl status jenkins-agent 2>/dev/null || journalctl --since '30 min ago' | grep -i agent

Confirm both sides run compatible Java, since a mismatch causes handshake-time channel closes:

# Controller
java -version
# Agent
ssh agent-01 'java -version'

From the Script Console, inspect the live channel state and configured ping settings:

// Which agents are online, and is the channel alive? (Script Console)
Jenkins.instance.computers.each { c ->
  println "${c.name}\tonline=${c.online}\tchannel=${c.channel != null}"
}

Fixes

1. Fix an OOM/killed agent JVM

If the agent died from memory pressure, raise the agent remoting heap and enable a dump so you can confirm it. For an inbound agent:

java -Xmx2g -XX:+UseG1GC \
  -XX:+HeapDumpOnOutOfMemoryError \
  -jar agent.jar -jnlpUrl https://jenkins.example.com/computer/agent-01/jenkins-agent.jnlp

Right-size the host and container memory so the kernel OOM-killer does not reap the JVM. See the heap-exhaustion guide linked below for sizing detail.

2. Tune the ping/keep-alive so blips do not kill healthy channels

If channels drop during long, quiet steps, the ping thread or a firewall idle timeout is the culprit. Increase tolerance under Manage Jenkins → System → (Advanced) TCP port / ping or via the remoting system properties on the controller:

# Controller JVM options — be more tolerant of transient stalls
JENKINS_JAVA_OPTIONS="-Dhudson.remoting.Launcher.pingIntervalSec=300 \
  -Dhudson.slaves.ChannelPinger.pingIntervalMinutes=10 \
  -Dhudson.slaves.ChannelPinger.pingTimeoutSeconds=240"

Do not disable pinging entirely — you want dead agents detected, just not healthy ones killed.

3. Keep the connection alive through firewalls / proxies

For inbound agents behind a reverse proxy, prefer the WebSocket transport, which survives proxies far better than raw TCP:

java -jar agent.jar -webSocket \
  -url https://jenkins.example.com/ -secret <agent-secret> -name agent-01

On the proxy, raise the idle/read timeout for the agent endpoint so long steps are not cut off, and enable TCP keep-alives on the agent host (net.ipv4.tcp_keepalive_time) so idle connections are refreshed before a stateful firewall expires them.

4. Make the build resilient and retry connection-level failures

A transient channel drop should not necessarily fail the whole pipeline. Wrap connection-sensitive work so it retries on a fresh executor:

pipeline {
  agent none
  stages {
    stage('Test') {
      steps {
        retry(count: 2) {
          node('linux') {
            timeout(time: 30, unit: 'MINUTES') {
              sh './run-tests.sh'
            }
          }
        }
      }
    }
  }
}

5. Align Java versions

Run the same major Java version (or a documented-compatible pair) on controller and all agents. Pin the agent image/base so an unattended upgrade cannot drift the JVM out of remoting compatibility.

What to watch out for

  • Channel "unknown" in the message is normal — remoting had not finished naming the channel, or it is already torn down. Do not read meaning into “unknown”; read the agent name in “Remote call to agent-01”.
  • Correlate timestamps across three logs (controller, agent, agent host kernel) before concluding — a channel close is a symptom whose cause lives on the far end.
  • Do not paper over a real OOM by cranking ping timeouts; you will just wait longer to see the same crash.
  • Watch for one flaky agent poisoning many builds. Take it offline and drain it rather than letting it keep failing jobs.
  • Sharing a JNLP secret across two agent processes causes constant channel flapping — one name, one running agent.
  • For live incidents, the free incident assistant can correlate the controller and agent logs for you.
Free download · 368-page PDF

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.