{"record":{"id":"79465306634d9d9f","repo":"jenkinsci/jenkins","slug":"unknown-operation","errorCode":null,"errorMessage":"unknown operation #{}","messagePattern":"unknown operation #(.+?)","errorType":"exception","errorClass":"ProtocolException","httpStatus":null,"severity":"error","filePath":"cli/src/main/java/hudson/cli/PlainCLIProtocol.java","lineNumber":192,"sourceCode":"    }\n\n    abstract static class EitherSide implements Closeable {\n\n        private final Output out;\n\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());","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/cli/src/main/java/hudson/cli/PlainCLIProtocol.java#L174-L210","documentation":"Thrown by EitherSide.handle when the opcode byte is non-negative but greater than or equal to Op.values().length. This means the peer sent an operation code the local side does not know about, indicating a version mismatch (newer client talking to older server, or vice versa).","triggerScenarios":"One side of the PlainCLIProtocol connection uses an Op enum that was extended in a newer Jenkins/CLI version while the other side runs an older build with fewer Op values.","commonSituations":"CLI jar downloaded from a newer Jenkins used against an older controller; controller upgraded but a bundled/older CLI jar is still in use.","solutions":["Align CLI jar and controller versions; fetch the CLI jar from the target controller's /jnlpJars/jenkins-cli.jar.","Upgrade both ends to the same Jenkins LTS line.","If you cannot upgrade, restrict CLI usage to operations supported by the older protocol version."],"exampleFix":"# before: mismatched versions\njava -jar /old/cli.jar -s http://new-jenkins ... \n# after\ncurl -sO http://new-jenkins/jnlpJars/jenkins-cli.jar && java -jar jenkins-cli.jar -s http://new-jenkins ...","handlingStrategy":"validation","validationCode":"// Before sending, ensure the local Op set is at least as large as the peer's\n// (compare CLI/protocol versions). If unknown opcodes are possible, negotiate a version.\nint maxOp = Arrays.stream(Op.values()).mapToInt(Enum::ordinal).max().getAsInt();\nif (peerMaxOp > maxOp) {\n    throw new IOException(\"Peer protocol version is newer; upgrade the CLI jar\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    side.handle(dis);\n} catch (ProtocolException e) {\n    if (e.getMessage().startsWith(\"unknown operation\")) {\n        // reconnect using a CLI jar version matching the controller\n    } else throw e;\n}","preventionTips":["Pin the CLI jar version to the controller version.","Re-download the CLI jar from the controller after a Jenkins upgrade.","Standardize on one Jenkins LTS line across servers you manage."],"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"}