quarkusio/quarkus · warning · NotEnoughDataDecoderException

Access out of bounds

Error message

Access out of bounds

What it means

skipControlCharacters advances through the undecoded chunk discarding ISO control chars and whitespace before reading the next delimiter/disposition line. If it runs past the end of available data without finding a non-control character, NotEnoughDataDecoderException('Access out of bounds') is thrown, signaling more data is needed.

Source

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

     */
    private static void skipControlCharacters(ByteBuf undecodedChunk) {
        if (!undecodedChunk.hasArray()) {
            try {
                skipControlCharactersStandard(undecodedChunk);
            } catch (IndexOutOfBoundsException e1) {
                throw new NotEnoughDataDecoderException(e1);
            }
            return;
        }
        QuarkusHttpPostBodyUtil.SeekAheadOptimize sao = new QuarkusHttpPostBodyUtil.SeekAheadOptimize(undecodedChunk);
        while (sao.pos < sao.limit) {
            char c = (char) (sao.bytes[sao.pos++] & 0xFF);
            if (!Character.isISOControl(c) && !Character.isWhitespace(c)) {
                sao.setReadPosition(1);
                return;
            }
        }
        throw new NotEnoughDataDecoderException("Access out of bounds");
    }

    private static void skipControlCharactersStandard(ByteBuf undecodedChunk) {
        for (;;) {
            char c = (char) undecodedChunk.readUnsignedByte();
            if (!Character.isISOControl(c) && !Character.isWhitespace(c)) {
                undecodedChunk.readerIndex(undecodedChunk.readerIndex() - 1);
                break;
            }
        }
    }

    /**
     * Find the next Multipart Delimiter
     *
     * @param delimiter
     *        delimiter to find
     * @param dispositionStatus

View on GitHub (pinned to e1c734241f)

Solutions

  1. Accumulate chunks and only offer complete buffers when possible; treat NotEnoughDataDecoderException as 'need more data'
  2. Check that the response is not truncated by the server/proxy (Content-Length vs actual bytes)
  3. Ensure the decoder is fed the full HttpContent for each chunk, not a stale view
  4. If the error persists on a complete response, inspect for corrupted boundary lines

Example fix

// before
try {
    decoder.offer(chunk);
} catch (NotEnoughDataDecoderException e) { /* treated as fatal */ }
// after
try {
    decoder.offer(chunk);
} catch (NotEnoughDataDecoderException e) {
    // normal: wait for the next chunk before continuing
}
Defensive patterns

Strategy: try-catch

Try / catch

try { decoder.offer(chunk); } catch (NotEnoughDataDecoderException e) { /* not fatal: buffer and wait for more data */ pending.add(chunk); }

Prevention

When it happens

Trigger: findMultipartDelimiter or findMultipartDisposition is invoked while the current undecoded chunk contains only whitespace/control bytes (or is exhausted), i.e. the boundary line hasn't arrived yet.

Common situations: Offering chunks one byte at a time (slow/fragmented responses); the client feeding partial buffers without accumulating; a truncated response ending in whitespace.

Related errors


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