MuntashirAkon/AppManager · error · IOException

Resetting to invalid mark

Error message

Resetting to invalid mark

What it means

SplitInputStream.reset() throws IOException("Resetting to invalid mark") when no valid mark position exists (mMarkPos < 0). As with InputStream generally, reset() is only legal after mark() has been called and the read limit has not been exceeded. The stream cannot rewind without a recorded mark.

Solutions

  1. Call mark(int readlimit) before reset() and ensure fewer than readlimit bytes are consumed
  2. Use markSupported() to verify support and guard the reset call
  3. Reopen or re-create the stream instead of resetting when no mark exists

Example fix

// before
stream.reset();
// after
if (stream.markSupported() && marked) {
    stream.reset();
} else {
    stream = reopenStream();
}
Defensive patterns

Strategy: validation

Validate before calling

if (stream.markSupported() && marked && consumedWithinLimit) stream.reset();

Type guard

boolean canReset(InputStream in, boolean marked) { return in.markSupported() && marked; }

Try / catch

try {
    stream.reset();
} catch (IOException e) {
    // no valid mark: reopen the stream instead
}

Prevention

When it happens

Trigger: Calling reset() on a SplitInputStream before ever calling mark(), or after reading more bytes than the marklimit supplied to mark(), which invalidates the mark.

Common situations: Parser code that assumes mark/reset support is always available; forgetting that mark() was never called on that stream instance; reading past the mark limit in a large buffer.

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 MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/a2f0bdf2769cd301. Report an issue: GitHub.

Appendix: source

Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/SplitInputStream.java:117

        // Reset mark
        mMarkPos = mPos;
        mMarkBufCount = 0;
        mMarkBuf = null;

        int remain = mCount - mPos;
        if (readlimit <= remain) {
            // Don't need a separate buffer
            mMarkBufSize = 0;
        } else {
            // Extra buffer required is remain + n * buf.length
            mMarkBufSize = remain + ((readlimit - remain) / mBuf.length) * mBuf.length;
        }
    }

    @Override
    public synchronized void reset() throws IOException {
        if (mMarkPos < 0)
            throw new IOException("Resetting to invalid mark");
        // Switch to markPos or use markBuf
        mPos = mMarkBuf == null ? mMarkPos : ~0;
    }

    @WorkerThread
    @Override
    public synchronized int available() throws IOException {
        if (mCount < 0) return 0;
        if (mPos >= mCount) {
            // Try to read the next chunk into memory
            read0(null, 0, 1);
            if (mCount < 0) return 0;
            // Revert the 1 byte read
            --mPos;
        }
        // Return the size available in memory
        if (mPos < 0) {
            return (mMarkBufCount - ~mPos) + mCount;

View on GitHub (pinned to 0152f468fc)