apache/dubbo · error · IOException
should mark before reset!
Error message
should mark before reset!
What it means
Thrown by the reset() of the mark-buffering InputStream from StreamUtils.markSupportedInputStream when reset() is called before mark() has ever been called (mInMarked is false). Reset requires a marked position to rewind to; without one there is no replay point, so it raises IOException("should mark before reset!"). This mirrors the contract of java.io.InputStream.reset().
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/io/StreamUtils.java:201
*/
@Override
public synchronized void mark(int readlimit) {
mInMarked = true;
mInReset = false;
// mark buffer is not empty
int count = mCount - mPosition;
if (count > 0) {
System.arraycopy(mMarkBuffer, mPosition, mMarkBuffer, 0, count);
mCount = count;
mPosition = 0;
}
}
@Override
public synchronized void reset() throws IOException {
if (!mInMarked) {
throw new IOException("should mark before reset!");
}
mInReset = true;
mPosition = 0;
}
@Override
public boolean markSupported() {
return true;
}
@Override
public int available() throws IOException {
int available = is.available();
if (mInMarked && mInReset) {
available += mCount - mPosition;
}View on GitHub (pinned to 3a3043227f)
Solutions
- Always pair: call mark(readlimit) before any reset() on the same instance.
- Track marked state yourself and only reset() when you have marked: if (marked) { m.reset(); marked = false; }
- Prefer try-with-resources and re-open the stream rather than relying on reset for replay when mark state is uncertain.
Example fix
// before InputStream m = StreamUtils.markSupportedInputStream(in); m.reset(); // -> IOException: should mark before reset! // after InputStream m = StreamUtils.markSupportedInputStream(in); m.mark(1024); // ... read ... m.reset();
Defensive patterns
Strategy: validation
Validate before calling
boolean marked = false;
m.mark(1024); marked = true;
// ... read ...
if (marked) { m.reset(); marked = false; } Try / catch
try {
m.reset();
} catch (IOException e) {
// no mark set — re-open the stream instead of replaying
in = reopen();
} Prevention
- Always pair mark() and reset() on the same instance.
- Track marked state in a local and only reset() when true.
- On error paths, ensure mark() actually ran before reset().
- Prefer re-opening the source when mark state is uncertain.
When it happens
Trigger: Calling reset() on a StreamUtils-marked stream without a prior mark(); calling reset() after the mark was implicitly cleared (e.g. after a full buffer cycle on some flows); reuse of a stream instance across operations where only the second calls reset().
Common situations: Reset-without-mark copy-paste; conditional code path that skips mark() on a fast path but still calls reset(); state machine that resets on error without ensuring mark happened.
Related errors
- Mark buffer is full!
- Negative initial size: ${size}
- Read-ahead limit < 0
- Stream closed
- Negative buffer size
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/9831448bfde5b471.
Report an issue: GitHub.