chinabugotech/hutool · error · IllegalStateException

Read limit exceeded

Error message

Read limit exceeded

What it means

LimitedInputStream caps the total bytes read or skipped at maxSize. Every read/skip increments currentPos and calls checkPos(); once currentPos exceeds maxSize it throws IllegalStateException("Read limit exceeded"). This is a deliberate DoS / decompression-bomb guard.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/io/LimitedInputStream.java:60

			currentPos += count;
			checkPos();
		}
		return count;
	}

	@Override
	public long skip(long n) throws IOException {
		final long skipped = super.skip(n);
		if (skipped != 0) {
			currentPos += skipped;
			checkPos();
		}
		return skipped;
	}

	private void checkPos() {
		if (currentPos > maxSize) {
			throw new IllegalStateException("Read limit exceeded");
		}
	}
}

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Set maxSize to the largest legitimate payload you expect to handle.
  2. Validate Content-Length / declared size before wrapping the stream.
  3. Catch IllegalStateException and reject the input as too large rather than treating it as a bug.

Example fix

// before: limit too small for real data
try (InputStream lim = new LimitedInputStream(in, 1024)) {
    byte[] all = IoUtil.readBytes(lim); // throws if payload > 1024
}

// after: size to expected maximum, and treat overflow as bad input
long max = 16L * 1024 * 1024;
try (InputStream lim = new LimitedInputStream(in, max)) {
    byte[] all = IoUtil.readBytes(lim);
} catch (IllegalStateException e) {
    throw new IllegalArgumentException("payload exceeds " + max + " bytes", e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

long declared = /* Content-Length or declared size */ -1;
if (declared > maxAllowed) {
    throw new IllegalArgumentException("payload too large: " + declared);
}
try (InputStream lim = new LimitedInputStream(in, maxAllowed)) {
    return IoUtil.readBytes(lim);
}

Try / catch

try (InputStream lim = new LimitedInputStream(in, maxSize)) {
    return IoUtil.readBytes(lim);
} catch (IllegalStateException e) {
    // read limit exceeded: input was larger than maxSize — reject as too large
    throw new IllegalArgumentException("input exceeds size limit " + maxSize, e);
}

Prevention

When it happens

Trigger: Reading or skipping more than maxSize bytes in total through a LimitedInputStream — e.g. decompressing a zip bomb or reading an oversized upload.

Common situations: Decompressing an archive bomb; maxSize set below the legitimate content size; reading an unbounded network payload without a content-length check; forgetting to size the limit to expected data.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/3af8ab97e0f0cdc5. Report an issue: GitHub.