MuntashirAkon/AppManager · error · IllegalStateException

Unexpected CharBuffer position: actual=" +…

Error message

Unexpected CharBuffer position: actual=" + mCharBuffer.position() + " expected=" + mCharBufferMark

What it means

reset() restores the stream to a previously set mark. The library throws IllegalStateException when, after refilling buffers, the CharBuffer position does not match the recorded mark (mCharBufferMark). This indicates an internal decoder buffering invariant was broken, typically because the internal buffers were consumed beyond the marked position.

Solutions

  1. Call mark(readLimit) with a readLimit large enough to cover all bytes read before reset().
  2. Always pair mark()/reset() and never reset() after the mark has been invalidated by excessive reads.
  3. Re-create the CharSequenceInputStream from the source CharSequence instead of resetting an exhausted mark.

Example fix

// before
stream.mark(8); stream.read(buf, 0, 1024); stream.reset();
// after
stream.mark(4096); stream.read(buf, 0, 1024); stream.reset();
Defensive patterns

Strategy: validation

Validate before calling

boolean canReset = !resetCalledOnce && bytesReadSinceMark < markedReadLimit;
if (!canReset) throw new IllegalStateException("Mark no longer valid");

Try / catch

try {
    stream.reset();
} catch (IllegalStateException e) {
    stream = new CharSequenceInputStream(source, charset); // recreate instead
}

Prevention

When it happens

Trigger: Calling reset() after reading past the marked region so far that the internal CharBuffer was refilled/rewound and its position can no longer be restored to mCharBufferMark (mark invalidated by too much reading since mark()).

Common situations: Calling reset() without a preceding mark(); reading more bytes than readLimit allows between mark() and reset(); calling reset() twice.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/873b6f71361bfec0. Report an issue: GitHub.

Appendix: source

Thrown at libcore/io/src/main/java/io/github/muntashirakon/io/CharSequenceInputStream.java:224

        // the mark. The code would have to catch InvalidMarkException - does not seem possible to check if mark is
        // valid otherwise. + Try saving the state of the cBuf before each fillBuffer; it might be possible to
        // restart from there.
        //
        if (mCharBufferMark != NO_MARK) {
            // if cBuf is at 0, we have not started reading anything, so skip re-encoding
            if (mCharBuffer.position() != 0) {
                mCharsetEncoder.reset();
                mCharBuffer.rewind();
                mByteBuffer.rewind();
                mByteBuffer.limit(0); // rewind does not clear the buffer
                while (mCharBuffer.position() < mCharBufferMark) {
                    mByteBuffer.rewind(); // empty the buffer (we only refill when empty during normal processing)
                    mByteBuffer.limit(0);
                    fillBuffer();
                }
            }
            if (mCharBuffer.position() != mCharBufferMark) {
                throw new IllegalStateException("Unexpected CharBuffer position: actual=" + mCharBuffer.position() + " " +
                        "expected=" + mCharBufferMark);
            }
            mByteBuffer.position(mByteBufferMark);
            mCharBufferMark = NO_MARK;
            mByteBufferMark = NO_MARK;
        }
    }

    @Override
    public long skip(long n) throws IOException {
        //
        // This could be made more efficient by using position to skip within the current buffer.
        //
        long skipped = 0;
        while (n > 0 && available() > 0) {
            read();
            n--;
            skipped++;

View on GitHub (pinned to 0152f468fc)