jenkinsci/jenkins · error · ProtocolException
unhandled: {}
Error message
unhandled: {} What it means
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).
Source
Thrown at cli/src/main/java/hudson/cli/PlainCLIProtocol.java:197
protected EitherSide(Output out) {
this.out = out;
}
protected abstract void handleClose();
final void handle(DataInputStream dis) throws IOException {
byte b = dis.readByte();
if (b < 0) { // i.e., >127
throw new IOException("corrupt stream: negative operation code");
}
if (b >= Op.values().length) {
throw new ProtocolException("unknown operation #" + b);
}
Op op = Op.values()[b];
LOGGER.finest(() -> "handling frame with " + op);
if (!handle(op, dis)) {
throw new ProtocolException("unhandled: " + op);
}
}
protected abstract boolean handle(Op op, DataInputStream dis) throws IOException;
protected final synchronized void send(Op op) throws IOException {
send(op, new byte[0], 0, 0);
}
protected final synchronized void send(Op op, int v) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream(4);
new DataOutputStream(baos).writeInt(v);
send(op, baos.toByteArray());
}
protected final synchronized void send(Op op, byte[] chunk, int off, int len) throws IOException {
byte[] data = new byte[len + 1];
data[0] = (byte) op.ordinal();View on GitHub (pinned to 2e228ff40b)
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.
Defensive patterns
Strategy: try-catch
Try / catch
try {
side.handle(dis);
} catch (ProtocolException e) {
if (e.getMessage().startsWith("unhandled:")) {
// log which Op was unhandled, reconnect with matching versions
LOGGER.log(WARNING, "Unhandled CLI op: {0}", e.getMessage());
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Protocol asymmetry between client and server builds; a partial upgrade where one side emits an Op the other recognizes but does not process.
Related errors
- unknown operation #{}
- expected to see initial zero byte; perhaps you are connectin
- corrupt stream: negative operation code
- corrupt stream: negative frame length
- There's no Jenkins running at {}
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/3d4d50db2406f44e.
Report an issue: GitHub.