bumptech/glide · error · InvalidMarkException
Mark has been invalidated, pos: {pos} markLimit: {marklimit}
Error message
Mark has been invalidated, pos: {pos} markLimit: {marklimit} What it means
InvalidMarkException (an IOException subclass) thrown by RecyclableBufferedInputStream.reset() when markpos == -1, meaning the mark has been invalidated because more than marklimit bytes were read between mark() and reset(). The buffered data was discarded to free memory.
Source
Thrown at library/src/main/java/com/bumptech/glide/load/resource/bitmap/RecyclableBufferedInputStream.java:344
}
offset += read;
}
}
/**
* Resets this stream to the last marked location.
*
* @throws IOException if this stream is closed, no mark has been put or the mark is no longer
* valid because more than {@code readlimit} bytes have been read since setting the mark.
* @see #mark(int)
*/
@Override
public synchronized void reset() throws IOException {
if (buf == null) {
throw new IOException("Stream is closed");
}
if (-1 == markpos) {
throw new InvalidMarkException(
"Mark has been invalidated, pos: " + pos + " markLimit: " + marklimit);
}
pos = markpos;
}
/**
* Skips {@code byteCount} bytes in this stream. Subsequent calls to {@link #read} will not return
* these bytes unless {@link #reset} is used.
*
* @param byteCount the number of bytes to skip. This method does nothing and returns 0 if {@code
* byteCount} is less than zero.
* @return the number of bytes actually skipped.
* @throws IOException if this stream is closed or another IOException occurs.
*/
@Override
public synchronized long skip(long byteCount) throws IOException {
if (byteCount < 1) {
return 0;View on GitHub (pinned to eb14a895d8)
Solutions
- Increase the marklimit passed to mark() to exceed the maximum bytes you will read before reset().
- Use a larger buffer size when constructing RecyclableBufferedInputStream.
- Avoid long read sequences between mark and reset; reset earlier or re-open the stream.
- For format detection, read the whole header into a byte array first, then parse from memory.
Example fix
// before is.mark(64); readFullHeader(is); // reads > 64 bytes is.reset(); // throws InvalidMarkException // after is.mark(HEADER_MAX_SIZE); // e.g. 8192 readFullHeader(is); is.reset();
Defensive patterns
Strategy: validation
Validate before calling
// Size marklimit to the maximum bytes you will read before reset. int maxReadBeforeReset = computeMaxHeaderSize(); is.mark(maxReadBeforeReset);
Try / catch
try { is.reset(); }
catch (RecyclableBufferedInputStream.InvalidMarkException e) {
// mark invalidated: reopen the stream and re-decode from start
} Prevention
- Set marklimit larger than any read you perform before reset.
- Reset as soon as you can, not after long reads.
- For header sniffing, read the whole header into memory first.
When it happens
Trigger: Calling mark(readlimit), then reading more than readlimit bytes, then calling reset(). The buffer cannot guarantee the marked position is still available, so reset is rejected.
Common situations: Decoders that probe far ahead of a small mark limit (e.g. header sniffing on formats with large headers). Custom InputStream wrappers with too-small mark limits passed to Glide.
Related errors
- BufferedInputStream is closed
- Stream is closed
- Cannot reset to unset mark position
- File too large to map into memory
- File unsuitable for memory mapping
AI-assisted analysis of bumptech/glide@eb14a895d8 (2026-08-14).
Data as JSON: /api/errors/f4634b0d245b1981.
Report an issue: GitHub.