Netflix/zuul · error · ZuulException
Received invalid message from client
Error message
Received invalid message from client
What it means
OriginResponseReceiver.writeInternal writes messages from the client side toward the origin connection and only accepts valid Zuul request/HTTP message types. If a write arrives with any other type, Zuul releases it and throws this error, since forwarding an unrecognized object to the origin would corrupt the proxied request. The 'should never happen' comment marks it as an internal invariant guard.
Solutions
- Locate the filter writing the invalid object (log msg.getClass() before the write) and convert it to the proper ZuulMessage/HttpRequest type.
- Ensure request filters set data via the Zuul session/message API (e.g. zuulRequest buffers/headers) rather than writing custom objects to the channel.
- Align custom filter code and zuul-core versions so request message types match.
- Audit pipeline customizations in the origin channel init for handlers that fire non-HTTP messages.
Example fix
// before (custom request filter) ctx.write(myCustomPayload); // after context.getZuulRequest().setBody(payloadBytes); // mutate the Zuul request message, don't write foreign objects
Defensive patterns
Strategy: validation
Validate before calling
// before writing toward the origin, assert the message is a supported Zuul/Netty request type
if (!(msg instanceof HttpRequest || msg instanceof HttpContent || msg instanceof ZuulMessage)) {
throw new IllegalArgumentException("Unsupported request message: " + msg.getClass().getName());
} Type guard
boolean isValidOriginRequest(Object msg) {
return msg instanceof HttpRequest || msg instanceof HttpContent || msg instanceof ZuulMessage;
} Try / catch
try {
ctx.write(msg);
} catch (ZuulException e) {
if ("Received invalid message from client".equals(e.getMessage())) {
log.error("Filter wrote invalid object to origin pipeline", e);
promise.setFailure(e);
}
} Prevention
- Mutate the Zuul request via its API (headers/body) instead of writing custom objects to the channel
- Only fire HttpRequest/HttpContent/ZuulMessage types into the origin-bound pipeline
- Integration-test custom request filters against a live Zuul pipeline before deploy
- Align custom filter dependencies with the running zuul-core version
When it happens
Trigger: An object that is not a recognized Zuul request message (e.g. raw String, ByteBuf, or custom object) is written into the origin-bound pipeline — typically from a custom pre-origin ZuulFilter or handler writing a foreign object type.
Common situations: Custom request filters mutating session/context and returning raw objects; version mismatches between custom filter code and zuul-core message APIs; errant pipeline handlers forwarding non-HTTP messages during proxying.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of Netflix/zuul@14bf53c52d (2026-09-07).
Data as JSON: /api/errors/f471fde9ac55528e.
Report an issue: GitHub.
Appendix: source
Thrown at zuul-core/src/main/java/com/netflix/zuul/netty/server/OriginResponseReceiver.java:256
fireWriteError("request headers", future.cause(), ctx);
}
}
});
preWriteHook(ctx, zuulReq);
super.write(ctx, buildOriginHttpRequest(zuulReq), promise);
} else if (msg instanceof HttpContent) {
promise.addListener((future) -> {
if (!future.isSuccess()) {
fireWriteError("request content chunk", future.cause(), ctx);
}
});
super.write(ctx, msg, promise);
} else {
// should never happen
ReferenceCountUtil.release(msg);
throw new ZuulException("Received invalid message from client", true);
}
}
/**
* Override to add custom pre-write functionality
*
* @param ctx channel handler context
* @param zuulReq request message to modify
*/
protected void preWriteHook(ChannelHandlerContext ctx, HttpRequestMessage zuulReq) {}
private void fireWriteError(String requestPart, Throwable cause, ChannelHandlerContext ctx) {
String errMesg = "Error while proxying " + requestPart + " to origin ";
if (edgeProxy != null) {
ProxyEndpoint ep = edgeProxy;
edgeProxy = null;
errMesg += ep.getOrigin().getName();
ep.errorFromOrigin(cause);View on GitHub (pinned to 14bf53c52d)