{"record":{"id":"3d4d50db2406f44e","repo":"jenkinsci/jenkins","slug":"unhandled","errorCode":null,"errorMessage":"unhandled: {}","messagePattern":"unhandled: (.+?)","errorType":"exception","errorClass":"ProtocolException","httpStatus":null,"severity":"error","filePath":"cli/src/main/java/hudson/cli/PlainCLIProtocol.java","lineNumber":197,"sourceCode":"\n        protected EitherSide(Output out) {\n            this.out = out;\n        }\n\n        protected abstract void handleClose();\n\n        final void handle(DataInputStream dis) throws IOException {\n            byte b = dis.readByte();\n            if (b < 0) { // i.e., >127\n                throw new IOException(\"corrupt stream: negative operation code\");\n            }\n            if (b >= Op.values().length) {\n                throw new ProtocolException(\"unknown operation #\" + b);\n            }\n            Op op = Op.values()[b];\n            LOGGER.finest(() -> \"handling frame with \" + op);\n            if (!handle(op, dis)) {\n                throw new ProtocolException(\"unhandled: \" + op);\n            }\n        }\n\n        protected abstract boolean handle(Op op, DataInputStream dis) throws IOException;\n\n        protected final synchronized void send(Op op) throws IOException {\n            send(op, new byte[0], 0, 0);\n        }\n\n        protected final synchronized void send(Op op, int v) throws IOException {\n            ByteArrayOutputStream baos = new ByteArrayOutputStream(4);\n            new DataOutputStream(baos).writeInt(v);\n            send(op, baos.toByteArray());\n        }\n\n        protected final synchronized void send(Op op, byte[] chunk, int off, int len) throws IOException {\n            byte[] data = new byte[len + 1];\n            data[0] = (byte) op.ordinal();","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/cli/src/main/java/hudson/cli/PlainCLIProtocol.java#L179-L215","documentation":"Thrown by EitherSide.handle when handle(Op, DataInputStream) returns false for a recognized opcode. Each concrete side returns false for an operation it does not expect to handle in that direction (e.g. a server-only Op received by the client, or an unimplemented handler).","triggerScenarios":"A frame's opcode is within the known range but the receiving side's handle(op) implementation has no branch for it (returns false), typically because the operation is meant for the opposite direction or a newer variant.","commonSituations":"Protocol asymmetry between client and server builds; a partial upgrade where one side emits an Op the other recognizes but does not process.","solutions":["Match the CLI jar version to the controller so both sides implement the same operation set.","If persisting, capture which Op triggered it (enable FINEST logging on hudson.cli.PlainCLIProtocol) and update the older side.","Fall back to SSH or Remoting CLI transport if the plain protocol remains incompatible."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    side.handle(dis);\n} catch (ProtocolException e) {\n    if (e.getMessage().startsWith(\"unhandled:\")) {\n        // log which Op was unhandled, reconnect with matching versions\n        LOGGER.log(WARNING, \"Unhandled CLI op: {0}\", e.getMessage());\n    } else throw e;\n}","preventionTips":["Keep client and server builds at the same protocol version.","Enable FINEST logging on hudson.cli.PlainCLIProtocol to capture the offending Op.","Have an SSH/Remoting fallback ready when the plain protocol misbehaves."],"tags":["jenkins-cli","protocol","version-mismatch","opcode"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}