OpenFeign/feign · error · IOException
Mark not set
Error message
Mark not set
What it means
CountingInputStream.reset() throws IOException("Mark not set") when reset() is called before any mark() has established a position (internal mark field is -1). Per InputStream contract, reset is only valid after a prior mark.
Solutions
- Call mark(readlimit) before any read if you plan to reset
- Restructure code to read the stream once and buffer the bytes if re-reading is needed
- Check markSupported() and your mark position logic before resetting
Example fix
// before is.read(); is.reset(); // Mark not set // after is.mark(8192); is.read(); is.reset();
Defensive patterns
Strategy: validation
Validate before calling
if (stream.markSupported() && markPositionSet) { stream.reset(); } Try / catch
try { stream.reset(); }
catch (IOException e) {
if ("Mark not set".equals(e.getMessage())) { stream.mark(8192); /* restart read */ }
else throw e;
} Prevention
- Call mark(readlimit) before any reset
- Track whether mark() was actually invoked
- Buffer bytes if replay semantics are needed
When it happens
Trigger: Calling reset() on the metered stream without ever calling mark(), or after the mark was invalidated; consuming more than readlimit then resetting.
Common situations: Custom retry/replay logic reading the response body twice; utility code assuming reset() always works; misuse of the CountingInputStream outside the Feign pipeline.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of OpenFeign/feign@e2a1e27560 (2026-09-10).
Data as JSON: /api/errors/46c1afa17dee3a06.
Report an issue: GitHub.
Appendix: source
Thrown at micrometer/src/main/java/feign/micrometer/CountingInputStream.java:88
final long result = in.skip(n);
count += result;
return result;
}
@Override
public synchronized void mark(int readlimit) {
in.mark(readlimit);
mark = count;
// it's okay to mark even if mark isn't supported, as reset won't work
}
@Override
public synchronized void reset() throws IOException {
if (!in.markSupported()) {
throw new IOException("Mark not supported");
}
if (mark == -1) {
throw new IOException("Mark not set");
}
in.reset();
count = mark;
}
}
View on GitHub (pinned to e2a1e27560)