jenkinsci/jenkins · critical · IOException
expected to see initial zero byte; perhaps you are connectin
Error message
expected to see initial zero byte; perhaps you are connecting to an old server which does not support -http?
What it means
Thrown during the plain (non-Remoting) CLI protocol over HTTP after FullDuplexHttpStream is established. The protocol expects the server to send an initial zero byte as a handshake; a non-zero first byte means the endpoint did not speak the '-http' plain CLI protocol. Typically indicates an old Jenkins server or a non-Jenkins endpoint.
Source
Thrown at cli/src/main/java/hudson/cli/CLI.java:429
return connection.exit();
}
}
private static int plainHttpConnection(String url, List<String> args, CLIConnectionFactory factory)
throws GeneralSecurityException, IOException, InterruptedException {
LOGGER.log(FINE, "Trying to connect to {0} via plain protocol over HTTP", url);
if (factory.noCertificateCheck) {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {new NoCheckTrustManager()}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((s, sslSession) -> true);
}
FullDuplexHttpStream streams = new FullDuplexHttpStream(new URL(url), "cli?remoting=false", factory.authorization);
try (ClientSideImpl connection = new ClientSideImpl(new PlainCLIProtocol.FramedOutput(streams.getOutputStream()))) {
connection.start(args);
InputStream is = streams.getInputStream();
if (is.read() != 0) { // cf. FullDuplexHttpService
throw new IOException("expected to see initial zero byte; perhaps you are connecting to an old server which does not support -http?");
}
new PlainCLIProtocol.FramedReader(connection, is).start();
new Thread("ping") { // JENKINS-46659
@Override
public void run() {
try {
Thread.sleep(PING_INTERVAL);
while (!connection.complete) {
LOGGER.fine("sending ping");
connection.sendEncoding(Charset.defaultCharset().name()); // no-op at this point
Thread.sleep(PING_INTERVAL);
}
} catch (IOException | InterruptedException x) {
LOGGER.log(Level.WARNING, null, x);
}
}
}.start();View on GitHub (pinned to 2e228ff40b)
Solutions
- Ensure the Jenkins controller is on a recent supported version that serves the plain CLI protocol over HTTP (the /cli?remoting=false endpoint).
- Match the CLI jar version to the controller version; download the CLI jar from the target controller's /jnlpJars/ path.
- If a proxy is in the path, bypass it for the CLI endpoint or reconfigure it to stream the response untouched.
Example fix
# before: CLI jar newer than the controller's protocol support java -jar cli.jar -s http://old-jenkins help # after: pull the matching CLI jar from the controller wget http://old-jenkins/jnlpJars/jenkins-cli.jar && java -jar jenkins-cli.jar -s http://old-jenkins help
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the controller serves the plain CLI protocol before connecting
HttpURLConnection c = (HttpURLConnection) new URL(baseUrl + "/cli?remoting=false").openConnection();
c.setRequestMethod("POST");
if (c.getResponseCode() != 200) {
throw new IOException("Controller does not support plain CLI over HTTP");
} Try / catch
try {
// plain protocol handshake
} catch (IOException e) {
if (e.getMessage().contains("initial zero byte")) {
// fall back to SSH or Remoting transport
} else throw e;
} Prevention
- Keep the CLI jar and controller on compatible versions.
- Prefer SSH transport when the HTTP path is behind aggressive proxies.
- Smoke-test the /cli endpoint after upgrading Jenkins.
When it happens
Trigger: CLI is run against a Jenkins version too old to support the plain CLI protocol over HTTP (pre-2.x or a version where the /cli endpoint was unavailable), or a proxy/firewall that injects a byte before the real response stream.
Common situations: Upgrading only the CLI jar while the controller stays on a very old version; a man-in-the-middle/proxy rewriting the response body; load balancer returning an error HTML page in place of the duplex stream.
Related errors
- unknown operation #{}
- unhandled: {}
- There's no Jenkins running at {}
- There's no Jenkins running at {}, or is not serving the HTTP
- corrupt stream: negative frame length
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/1325838569bd9cf6.
Report an issue: GitHub.