chinabugotech/hutool · error · IllegalArgumentException

The InputStream must not be null

Error message

The InputStream must not be null

What it means

IoUtil.readObj(ValidateObjectInputStream, Class) deserializes an object from a validated object stream. It immediately rejects a null input stream with IllegalArgumentException("The InputStream must not be null") before any deserialization is attempted.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java:609

	/**
	 * 从流中读取对象,即对象的反序列化,读取后不关闭流
	 *
	 * <p>
	 * 此方法使用了{@link ValidateObjectInputStream}中的黑白名单方式过滤类,用于避免反序列化漏洞<br>
	 * 通过构造{@link ValidateObjectInputStream},调用{@link ValidateObjectInputStream#accept(Class[])}
	 * 或者{@link ValidateObjectInputStream#refuse(Class[])}方法添加可以被序列化的类或者禁止序列化的类。
	 * </p>
	 *
	 * @param <T>   读取对象的类型
	 * @param in    输入流,使用{@link ValidateObjectInputStream}中的黑白名单方式过滤类,用于避免反序列化漏洞
	 * @param clazz 读取对象类型
	 * @return 输出流
	 * @throws IORuntimeException IO异常
	 * @throws UtilException      ClassNotFoundException包装
	 */
	public static <T> T readObj(ValidateObjectInputStream in, Class<T> clazz) throws IORuntimeException, UtilException {
		if (in == null) {
			throw new IllegalArgumentException("The InputStream must not be null");
		}
		if(null != clazz){
			in.accept(clazz);
		}
		try {
			//noinspection unchecked
			return (T) in.readObject();
		} catch (IOException e) {
			throw new IORuntimeException(e);
		} catch (ClassNotFoundException e) {
			throw new UtilException(e);
		}
	}

	/**
	 * 从流中读取内容,使用UTF-8编码
	 *
	 * @param <T>        集合类型

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Null-check the stream before calling readObj.
  2. Construct the ValidateObjectInputStream in a try-with-resources so it is never null at the call site.
  3. Use Objects.requireNonNull(stream) for an early, explicit failure.

Example fix

// before
T obj = IoUtil.readObj(vois, MyClass.class); // vois may be null

// after
try (ValidateObjectInputStream vo = new ValidateObjectInputStream(in)) {
    vo.accept(MyClass.class);
    T obj = IoUtil.readObj(vo, MyClass.class);
}
Defensive patterns

Strategy: validation

Validate before calling

if (in == null) {
    throw new IllegalArgumentException("ValidateObjectInputStream must not be null");
}
return IoUtil.readObj(in, clazz);

Type guard

static boolean isOpenStream(ValidateObjectInputStream s) {
    return s != null; // ObjectInputStream is open once constructed
}

Try / catch

try {
    return IoUtil.readObj(vois, clazz);
} catch (IllegalArgumentException e) {
    // stream was null: open one and retry
}

Prevention

When it happens

Trigger: Calling IoUtil.readObj(null, clazz) — passing a null ValidateObjectInputStream.

Common situations: The stream was never opened due to an earlier failure; a resource lookup returned null; a conditional branch left the stream variable unset.

Related errors


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