quarkusio/quarkus · error · IllegalArgumentException

buffer hasn't backing byte array

Error message

buffer hasn't backing byte array

What it means

QuarkusHttpPostBodyUtil.SeekAheadOptimize is a fast-path optimization that requires the ByteBuf to have a backing JVM byte array. If buffer.hasArray() is false (e.g. direct or composite buffers), it throws IllegalArgumentException.

Source

Thrown at independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/multipart/QuarkusHttpPostBodyUtil.java:99

    /**
     * This class intends to decrease the CPU in seeking ahead some bytes in
     * HttpPostRequestDecoder
     */
    static class SeekAheadOptimize {
        byte[] bytes;
        int readerIndex;
        int pos;
        int origPos;
        int limit;
        ByteBuf buffer;

        /**
         * @param buffer buffer with a backing byte array
         */
        SeekAheadOptimize(ByteBuf buffer) {
            if (!buffer.hasArray()) {
                throw new IllegalArgumentException("buffer hasn't backing byte array");
            }
            this.buffer = buffer;
            bytes = buffer.array();
            readerIndex = buffer.readerIndex();
            origPos = pos = buffer.arrayOffset() + readerIndex;
            limit = buffer.arrayOffset() + buffer.writerIndex();
        }

        /**
         *
         * @param minus this value will be used as (currentPos - minus) to set
         *        the current readerIndex in the buffer.
         */
        void setReadPosition(int minus) {
            pos -= minus;
            readerIndex = getReadPosition(pos);
            buffer.readerIndex(readerIndex);
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Use the fallback seek-ahead-disabled parsing path (parsing directly on the ByteBuf) when the buffer has no array
  2. Force heap-buffer allocation for multipart request bodies (e.g. -Dio.netty.maxDirectMemory=0)
  3. Copy the buffer into a heap buffer (Unpooled.copiedBuffer / alloc.ioBuffer) before constructing SeekAheadOptimize

Example fix

// before
SeekAheadOptimize sao = new SeekAheadOptimize(buffer);
// after
SeekAheadOptimize sao = buffer.hasArray() ? new SeekAheadOptimize(buffer) : null; // fall back to non-optimized path
Defensive patterns

Strategy: validation

Validate before calling

if (!buffer.hasArray()) { /* use the non-optimized parsing path */ }

Type guard

null

Try / catch

try { sao = new SeekAheadOptimize(buffer); } catch (IllegalArgumentException e) { sao = null; /* seek-ahead disabled */ }

Prevention

When it happens

Trigger: Constructing SeekAheadOptimize with a direct (off-heap) ByteBuf or a composite/unpooled buffer without a backing array.

Common situations: Netty allocating direct buffers (default with io.netty.maxDirectMemory enabled) for multipart bodies; pooling configurations changed by flags or Netty version upgrades.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/b424f38dc18a9998. Report an issue: GitHub.