NationalSecurityAgency/ghidra · error · IOException

No mark

Error message

No mark

What it means

Thrown (checked IOException) by DBBufferInputStream.reset() when mark is -1, i.e. mark() was never called (or the mark was invalidated/reset). Per InputStream semantics reset() returns to the marked position; with no mark there is no valid position to return to, so it refuses. mark is initialized to -1 and only set by mark().

Source

Thrown at Ghidra/Debug/ProposedUtils/src/main/java/ghidra/util/database/DBBufferInputStream.java:108

	@Override
	public int readNBytes(byte[] b, int off, int len) throws IOException {
		return read(b, off, len);
	}

	@Override
	public byte[] readNBytes(int len) throws IOException {
		len = Math.min(available(), len);
		byte[] result = new byte[len];
		buffer.get(offset, result);
		offset += len;
		return result;
	}

	@Override
	public synchronized void reset() throws IOException {
		if (mark == -1) {
			throw new IOException("No mark");
		}
		offset = mark;
	}

	@Override
	public long skip(long n) throws IOException {
		if (n < 0) {
			return 0;
		}
		n = Math.min(available(), n);
		offset += n;
		return n;
	}
}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Call mark(readAheadLimit) before reset(); guard reset with a check that mark has been set.
  2. Track whether you have marked (boolean) rather than assuming mark is valid.
  3. If you need to re-read from the start, re-open the stream or seek to offset 0 instead of relying on reset.

Example fix

// before
in.reset(); // throws IOException "No mark"

// after: mark first, and only reset if marked
in.mark(Integer.MAX_VALUE);
// ... read ...
if (wasMarked) {
    in.reset();
}
Defensive patterns

Strategy: validation

Validate before calling

// Only reset if a mark has been set
if (markWasSet) {
    in.reset();
} else {
    // call in.mark(readAhead) first, or re-open the stream
}

Try / catch

try {
    in.reset();
} catch (IOException e) {
    if ("No mark".equals(e.getMessage())) { /* mark first, then reset */ }
    else throw e;
}

Prevention

When it happens

Trigger: Calling reset() before mark() has ever been called on the stream, or after the stream state reset mark back to -1. Mirrors standard java.io.InputStream behavior where reset-without-mark is an error.

Common situations: Reusing a DBBufferInputStream and calling reset() assuming a default mark of 0; copy/scan loops that reset without a preceding mark; generic stream-processing code that assumes markSupported()+reset always works.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/19d155b28704d228. Report an issue: GitHub.