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

  1. Wrap the source in a BufferedInputStream (or push the data into a byte[] and use ByteArrayInputStream) before constructing BinaryDataInputStream
  2. Check markSupported() before mark()/reset() and fail early with a clear message
  3. If random access is needed, prefer a RandomAccessFile/seek-based reader instead of mark/reset
  4. 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

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


AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14). Data as JSON: /api/errors/f3f0b5d1605825f3. Report an issue: GitHub.