iBotPeaches/Apktool · error · IOException
Mark not supported
Error message
Mark not supported
What it means
BinaryDataInputStream.reset() checks markSupported() and throws when the wrapped stream cannot support mark/reset. The class itself tracks a logical mark position, but it delegates the actual rewind to the underlying InputStream — if that stream lacks mark support, rewinding is impossible.
Source
Thrown at brut.j.util/src/main/java/brut/util/BinaryDataInputStream.java:342
return skipped;
}
@Override
public int available() throws IOException {
return (int) Math.min(in.available(), remaining());
}
@Override
public synchronized void mark(int readlimit) {
// We can't throw an exception here, so mark even if mark isn't supported, since reset won't work anyway.
in.mark(readlimit);
mMark = mPosition;
}
@Override
public synchronized void reset() throws IOException {
if (!markSupported()) {
throw new IOException("Mark not supported");
}
if (mMark == -1) {
throw new IOException("Mark not set");
}
in.reset();
mPosition = mMark;
}
}
View on GitHub (pinned to 79b63384d7)
Solutions
- Wrap the source in a BufferedInputStream (or push the data into a byte[] and use ByteArrayInputStream) before constructing BinaryDataInputStream
- Check markSupported() before mark()/reset() and fail early with a clear message
- If random access is needed, prefer a RandomAccessFile/seek-based reader instead of mark/reset
- Size the buffer >= the maximum bytes you will read between mark and reset
Example fix
// before
BinaryDataInputStream in = new BinaryDataInputStream(new FileInputStream(file), ...);
in.mark(1024);
... in.read ... ;
in.reset(); // Mark not supported
// after
BinaryDataInputStream in = new BinaryDataInputStream(
new BufferedInputStream(new FileInputStream(file), 1 << 16), ...);
in.mark(1 << 16);
in.reset(); // works Defensive patterns
Strategy: validation
Validate before calling
InputStream src = new FileInputStream(file);
if (!src.markSupported()) {
src = new BufferedInputStream(src, 1 << 16); // now markSupported() == true
}
BinaryDataInputStream in = new BinaryDataInputStream(src, ...);
assert in.markSupported(); Type guard
boolean canMarkReset(BinaryDataInputStream in) {
return in.markSupported();
} Try / catch
try {
in.reset();
} catch (IOException e) {
if ("Mark not supported".equals(e.getMessage())) {
// rewrap source with BufferedInputStream and restart the parse; retrying reset() is pointless
} else { throw e; }
} Prevention
- Always wrap file/socket streams in BufferedInputStream before parsing
- Check markSupported() once at construction and fail fast
- Prefer seek-based (RandomAccessFile) access when you need arbitrary rewinds
When it happens
Trigger: Calling reset() on a BinaryDataInputStream wrapping a raw FileInputStream, Socket stream, or other non-buffering InputStream after a mark() call; mark() silently records the position but reset() cannot honor it.
Common situations: Parsing code that worked with a buffered or byte-array stream being pointed at a file/socket stream; refactoring parsers to read straight from channels; testing with ByteArrayInputStream (works) then failing in production with FileInputStream.
Related errors
- Mark not set
- Could not move file:
- Could not copy file:
- Could not generate:
- Could not decode arsc file.
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/f3f0b5d1605825f3.
Report an issue: GitHub.