netty/netty · error · IllegalStateException

decoder properties cannot be changed once the decoder is add

Error message

decoder properties cannot be changed once the decoder is added to a pipeline.

What it means

Decoder/aggregator tuning properties (like maxCumulationBufferComponents) may only be changed BEFORE the handler is added to the pipeline. Once ctx is set (handler added), setMaxCumulationBufferComponents throws IllegalStateException to prevent unsafe concurrent mutation during decoding.

Source

Thrown at codec-base/src/main/java/io/netty/handler/codec/MessageAggregator.java:185

    /**
     * Sets the maximum number of components in the cumulation buffer.  If the number of
     * the components in the cumulation buffer exceeds this value, the components of the
     * cumulation buffer are consolidated into a single component, involving memory copies.
     * The default value of this property is {@value #DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS}
     * and its minimum allowed value is {@code 2}.
     */
    public final void setMaxCumulationBufferComponents(int maxCumulationBufferComponents) {
        if (maxCumulationBufferComponents < 2) {
            throw new IllegalArgumentException(
                    "maxCumulationBufferComponents: " + maxCumulationBufferComponents +
                    " (expected: >= 2)");
        }

        if (ctx == null) {
            this.maxCumulationBufferComponents = maxCumulationBufferComponents;
        } else {
            throw new IllegalStateException(
                    "decoder properties cannot be changed once the decoder is added to a pipeline.");
        }
    }

    /**
     * @deprecated This method will be removed in future releases.
     */
    @Deprecated
    public final boolean isHandlingOversizedMessage() {
        return handlingOversizedMessage;
    }

    protected final ChannelHandlerContext ctx() {
        if (ctx == null) {
            throw new IllegalStateException("not added to a pipeline yet");
        }
        return ctx;
    }

View on GitHub (pinned to 70040aacae)

Solutions

  1. Set all properties before adding the handler to the pipeline (before bootstrap / channel setup).
  2. Create a fresh handler instance per channel with the desired config instead of mutating a shared one.
  3. If runtime change is required, replace the handler in the pipeline with a new configured instance.

Example fix

// before
ch.pipeline().addLast(aggregator);
aggregator.setMaxCumulationBufferComponents(16); // throws

// after
aggregator.setMaxCumulationBufferComponents(16);
ch.pipeline().addLast(aggregator);
Defensive patterns

Strategy: validation

Validate before calling

// Configure BEFORE adding to pipeline:
aggregator.setMaxCumulationBufferComponents(n);
assert pipeline.get(aggregator.getClass()) == null : "handler already in pipeline";

Prevention

When it happens

Trigger: Calling aggregator.setMaxCumulationBufferComponents(...) after the aggregator was already added to a ChannelPipeline (ctx != null).

Common situations: Reconfiguring a shared handler instance at runtime; lazy-init code that configures after channel creation; hot-reloading config without recreating the handler; reusing a handler across channels.

Related errors


AI-assisted analysis of netty/netty@70040aacae (2026-08-14). Data as JSON: /api/errors/c94453503cc86e96. Report an issue: GitHub.