{"record":{"id":"e8ce4f7406859952","repo":"jenkinsci/jenkins","slug":"corrupt-stream-negative-frame-length","errorCode":null,"errorMessage":"corrupt stream: negative frame length","messagePattern":"corrupt stream: negative frame length","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"cli/src/main/java/hudson/cli/PlainCLIProtocol.java","lineNumber":136,"sourceCode":"            cis = new CountingInputStream(is);\n            flightRecorder = new FlightRecorderInputStream(cis);\n            dis = new DataInputStream(flightRecorder);\n        }\n\n        @Override\n        public void run() {\n            try {\n                while (true) {\n                    LOGGER.finest(\"reading frame\");\n                    int framelen;\n                    try {\n                        framelen = dis.readInt();\n                    } catch (EOFException x) {\n                        side.handleClose();\n                        break; // TODO verify that we hit EOF immediately, not partway into framelen\n                    }\n                    if (framelen < 0) {\n                        throw new IOException(\"corrupt stream: negative frame length\");\n                    }\n                    LOGGER.finest(\"read frame length \" + framelen);\n                    long start = cis.getByteCount();\n                    try {\n                        side.handle(new DataInputStream(new BoundedInputStream(dis, /* op byte not counted */framelen + 1)));\n                    } catch (ProtocolException x) {\n                        LOGGER.log(Level.WARNING, null, x);\n                        // but read another frame\n                    } finally {\n                        long actuallyRead = cis.getByteCount() - start;\n                        long unread = framelen + 1 - actuallyRead;\n                        if (unread > 0) {\n                            LOGGER.warning(() -> \"Did not read \" + unread + \" bytes\");\n                            IOUtils.skipFully(dis, unread);\n                        }\n                    }\n                }\n            } catch (ClosedChannelException x) {","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/cli/src/main/java/hudson/cli/PlainCLIProtocol.java#L118-L154","documentation":"Thrown by PlainCLIProtocol.FramedReader when the 4-byte frame length read from the stream is negative. The protocol defines each frame as a nonnegative int length followed by a one-byte opcode and payload; a negative length is impossible in a well-formed stream and signals corruption or a version/protocol mismatch.","triggerScenarios":"The bytes being read are not actually a PlainCLIProtocol stream (e.g. an HTML error page, an HTTP chunk header, or random data), or the two sides disagree on framing (one side sending Remoting, the expecting plain).","commonSituations":"A proxy injecting content into the CLI stream; server returning a login/error page instead of framed bytes; client and server CLI protocol versions mismatched; connection half-closed and reusing a stale socket.","solutions":["Verify the -s URL and credentials so Jenkins returns the framed protocol rather than an error/login page.","Use a CLI jar version matching the controller to avoid framing disagreements.","Inspect the network path for any proxy that might alter the response body."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    new PlainCLIProtocol.FramedReader(connection, is).start();\n} catch (IOException e) {\n    if (e.getMessage().contains(\"negative frame length\")) {\n        // reconnect with a matched CLI jar version; the stream was not the expected protocol\n    } else throw e;\n}","preventionTips":["Use a CLI jar downloaded from the target controller to avoid framing mismatches.","Keep the CLI connection free of intercepting proxies.","Authenticate so Jenkins returns framed bytes rather than a login page."],"tags":["jenkins-cli","protocol","stream-corruption","framing"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}