grpc/grpc-java · error · IllegalStateException
Cannot disable auto flow control after call started. Use…
Error message
Cannot disable auto flow control after call started. Use ClientResponseObserver
What it means
ClientCalls' ClientCallStreamObserver throws IllegalStateException if disableAutoRequestWithInitial is called after the call is frozen (started). Disabling automatic inbound flow control must be configured before the RPC begins, typically via ClientResponseObserver.beforeStart.
Solutions
- Implement the response observer as ClientResponseObserver and call disableAutoRequestWithInitial in beforeStart()
- Ensure the wrapper disables auto flow control before passing the observer to async*() methods
- Keep request() calls manual from the very start of the stream
Example fix
// before
observer.disableAutoInboundFlowControl(); // called after start -> throws
// after
public void beforeStart(ClientCallStreamObserver<Req> obs) { obs.disableAutoInboundFlowControl(); } Defensive patterns
Strategy: type-guard
Try / catch
try { observer.disableAutoInboundFlowControl(); } catch (IllegalStateException e) { throw new IllegalStateException("Disable auto flow control in ClientResponseObserver.beforeStart", e); } Prevention
- Call disableAutoRequestWithInitial in beforeStart only
- Design wrappers to configure before call start
- Keep manual request() logic initialized from stream start
When it happens
Trigger: Calling disableAutoInboundFlowControl()/disableAutoRequestWithInitial on the stream observer after starting an async call and receiving any observer callback.
Common situations: Setting up manual request() flow control lazily; copying Netty/channel option patterns to the observer API; libraries wrapping observers that configure after first message.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot alter onReadyHandler after call started. Use…
- ChannelLogger is not set in Builder
- Framer already closed
- halfClose cannot be called after already half closed or…
- Invalid initial window size
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/d8b48fc3dba1f9ac.
Report an issue: GitHub.
Appendix: source
Thrown at stub/src/main/java/io/grpc/stub/ClientCalls.java:505
@Override
public void setOnReadyHandler(Runnable onReadyHandler) {
if (frozen) {
throw new IllegalStateException(
"Cannot alter onReadyHandler after call started. Use ClientResponseObserver");
}
this.onReadyHandler = onReadyHandler;
}
@Override
public void disableAutoInboundFlowControl() {
disableAutoRequestWithInitial(1);
}
@Override
public void disableAutoRequestWithInitial(int request) {
if (frozen) {
throw new IllegalStateException(
"Cannot disable auto flow control after call started. Use ClientResponseObserver");
}
Preconditions.checkArgument(request >= 0, "Initial requests must be non-negative");
initialRequest = request;
autoRequestEnabled = false;
}
@Override
public void request(int count) {
if (!streamingResponse && count == 1) {
// Initially ask for two responses from flow-control so that if a misbehaving server
// sends more than one response, we can catch it and fail it in the listener.
call.request(2);
} else {
call.request(count);
}
}
View on GitHub (pinned to 64daddc1f3)