apache/dubbo · error · IOException

Mark buffer is full!

Error message

Mark buffer is full!

What it means

Thrown by the mark-buffering InputStream created in StreamUtils.markSupportedInputStream(InputStream, int markBufferSize) when, after mark() has been set, the number of bytes read exceeds markBufferSize. This wrapper is used only when the underlying stream does not support mark/reset itself; it buffers bytes between mark() and reset() in a fixed-size array, and once mPosition reaches markBufferSize it raises IOException("Mark buffer is full!"). It is the direct analogue of java.io's 'Read ahead limit exceeded' but with an explicit, user-controlled cap.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/io/StreamUtils.java:155

            public int read() throws IOException {
                if (!mInMarked) {
                    return is.read();
                } else {
                    if (mPosition < mCount) {
                        byte b = mMarkBuffer[mPosition++];
                        return b & 0xFF;
                    }

                    if (!mInReset) {
                        if (mDry) {
                            return -1;
                        }

                        if (null == mMarkBuffer) {
                            mMarkBuffer = new byte[markBufferSize];
                        }
                        if (mPosition >= markBufferSize) {
                            throw new IOException("Mark buffer is full!");
                        }

                        int read = is.read();
                        if (-1 == read) {
                            mDry = true;
                            return -1;
                        }

                        mMarkBuffer[mPosition++] = (byte) read;
                        mCount++;

                        return read;
                    } else {
                        // mark buffer is used, exit mark status!
                        mInMarked = false;
                        mInReset = false;
                        mPosition = 0;
                        mCount = 0;

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Size markBufferSize to the maximum bytes you will read between mark() and reset(), e.g. markSupportedInputStream(in, requiredLookahead).
  2. Call reset() as early as possible once the decision point is passed, to free the buffer.
  3. Avoid wrapping already-markable streams (the wrapper returns the original unchanged when markSupported() is true).

Example fix

// before
InputStream m = StreamUtils.markSupportedInputStream(in); // default cap too small
m.mark(64);
// ... read 4KB to inspect ...
m.reset(); // -> IOException: Mark buffer is full!
// after
InputStream m = StreamUtils.markSupportedInputStream(in, 8 * 1024); // cap >= lookahead
m.mark(64);
// ... read up to 8KB ...
m.reset();
Defensive patterns

Strategy: validation

Validate before calling

int requiredLookahead = 8 * 1024; // >= max bytes between mark() and reset()
InputStream m = StreamUtils.markSupportedInputStream(in, requiredLookahead);
m.mark(requiredLookahead);

Type guard

static int markBufferSizeFor(int maxReadAhead) {
    return Math.max(maxReadAhead, 1);
}

Try / catch

try {
    m.reset();
} catch (IOException e) {
    // buffer too small — re-open the source and re-read instead of replaying
    in = reopen(); m = StreamUtils.markSupportedInputStream(in, biggerCap);
}

Prevention

When it happens

Trigger: Wrapping a non-markable stream with markSupportedInputStream(in, N), calling mark(N), then reading more than N bytes before reset(); or calling the single-arg markSupportedInputStream(in) whose default buffer is too small for the replay window.

Common situations: Replaying HTTP response bodies, multipart parsing, or protocol peeking where the consumed-ahead bytes exceed the configured buffer; default buffer size used for a stream that needs a large lookahead; mark(readlimit) ignored — this implementation ignores readlimit and uses the constructor cap.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/d73a2e8f0b55376e. Report an issue: GitHub.