{"record":{"id":"1325838569bd9cf6","repo":"jenkinsci/jenkins","slug":"expected-to-see-initial-zero-byte-perhaps-you-are","errorCode":null,"errorMessage":"expected to see initial zero byte; perhaps you are connecting to an old server which does not support -http?","messagePattern":"expected to see initial zero byte; perhaps you are connecting to an old server which does not support -http\\?","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"critical","filePath":"cli/src/main/java/hudson/cli/CLI.java","lineNumber":429,"sourceCode":"            return connection.exit();\n        }\n    }\n\n    private static int plainHttpConnection(String url, List<String> args, CLIConnectionFactory factory)\n            throws GeneralSecurityException, IOException, InterruptedException {\n        LOGGER.log(FINE, \"Trying to connect to {0} via plain protocol over HTTP\", url);\n        if (factory.noCertificateCheck) {\n            SSLContext sslContext = SSLContext.getInstance(\"TLS\");\n            sslContext.init(null, new TrustManager[] {new NoCheckTrustManager()}, new SecureRandom());\n            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());\n            HttpsURLConnection.setDefaultHostnameVerifier((s, sslSession) -> true);\n        }\n        FullDuplexHttpStream streams = new FullDuplexHttpStream(new URL(url), \"cli?remoting=false\", factory.authorization);\n        try (ClientSideImpl connection = new ClientSideImpl(new PlainCLIProtocol.FramedOutput(streams.getOutputStream()))) {\n            connection.start(args);\n            InputStream is = streams.getInputStream();\n            if (is.read() != 0) { // cf. FullDuplexHttpService\n                throw new IOException(\"expected to see initial zero byte; perhaps you are connecting to an old server which does not support -http?\");\n            }\n            new PlainCLIProtocol.FramedReader(connection, is).start();\n            new Thread(\"ping\") { // JENKINS-46659\n                @Override\n                public void run() {\n                    try {\n                        Thread.sleep(PING_INTERVAL);\n                        while (!connection.complete) {\n                            LOGGER.fine(\"sending ping\");\n                            connection.sendEncoding(Charset.defaultCharset().name()); // no-op at this point\n                            Thread.sleep(PING_INTERVAL);\n                        }\n                    } catch (IOException | InterruptedException x) {\n                        LOGGER.log(Level.WARNING, null, x);\n                    }\n                }\n\n            }.start();","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/cli/src/main/java/hudson/cli/CLI.java#L411-L447","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: CLI jar newer than the controller's protocol support\njava -jar cli.jar -s http://old-jenkins help\n# after: pull the matching CLI jar from the controller\nwget http://old-jenkins/jnlpJars/jenkins-cli.jar && java -jar jenkins-cli.jar -s http://old-jenkins help","handlingStrategy":"validation","validationCode":"// Confirm the controller serves the plain CLI protocol before connecting\nHttpURLConnection c = (HttpURLConnection) new URL(baseUrl + \"/cli?remoting=false\").openConnection();\nc.setRequestMethod(\"POST\");\nif (c.getResponseCode() != 200) {\n    throw new IOException(\"Controller does not support plain CLI over HTTP\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    // plain protocol handshake\n} catch (IOException e) {\n    if (e.getMessage().contains(\"initial zero byte\")) {\n        // fall back to SSH or Remoting transport\n    } else throw e;\n}","preventionTips":["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."],"tags":["jenkins-cli","protocol","version-mismatch","network"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}