chinabugotech/hutool · error · IllegalArgumentException

Default value [{}]({}) is not the instance of [{}]

Error message

Default value [{}]({}) is not the instance of [{}]

What it means

AbstractConverter.convert requires a non-null defaultValue to be an instance of the converter's targetType. If defaultValue is not null and not targetType.isInstance(defaultValue), it throws IllegalArgumentException.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/convert/AbstractConverter.java:61

			throw new NullPointerException(StrUtil.format("[type] and [defaultValue] are both null for Converter [{}], we can not know what type to convert !", this.getClass().getName()));
		}
		if (null == targetType) {
			// 目标类型不确定时使用默认值的类型
			targetType = (Class<T>) defaultValue.getClass();
		}
		if (null == value) {
			return defaultValue;
		}

		if (null == defaultValue || targetType.isInstance(defaultValue)) {
			if (targetType.isInstance(value) && false == Map.class.isAssignableFrom(targetType)) {
				// 除Map外,已经是目标类型,不需要转换(Map类型涉及参数类型,需要单独转换)
				return targetType.cast(value);
			}
			final T result = convertInternal(value);
			return ((null == result) ? defaultValue : result);
		} else {
			throw new IllegalArgumentException(
				StrUtil.format("Default value [{}]({}) is not the instance of [{}]", defaultValue, defaultValue.getClass(), targetType));
		}
	}

	/**
	 * 内部转换器,被 {@link AbstractConverter#convert(Object, Object)} 调用,实现基本转换逻辑<br>
	 * 内部转换器转换后如果转换失败可以做如下操作,处理结果都为返回默认值:
	 *
	 * <pre>
	 * 1、返回{@code null}
	 * 2、抛出一个{@link RuntimeException}异常
	 * </pre>
	 *
	 * @param value 值
	 * @return 转换后的类型
	 */
	protected abstract T convertInternal(Object value);

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Supply a defaultValue whose type matches (or is a subtype of) targetType.
  2. Pass null as the default if you do not need a fallback.
  3. Use convertQuietly(value, defaultValue) which swallows the exception and returns the default on failure.

Example fix

// before - default type mismatch
Integer i = intConverter.convert(value, "0");

// after - matching default
Integer i = intConverter.convert(value, 0);
Defensive patterns

Strategy: type-guard

Validate before calling

Class<T> tt = converter.getTargetType();
if (defaultValue != null && tt != null && !tt.isInstance(defaultValue)) {
    throw new IllegalArgumentException("default " + defaultValue + " not a " + tt);
}
converter.convert(value, defaultValue);

Type guard

default != null && converter.getTargetType() != null && converter.getTargetType().isInstance(defaultValue)

Try / catch

try {
    converter.convert(value, defaultValue);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("not the instance of")) { /* fix default type */ }
    else throw e;
}

Prevention

When it happens

Trigger: Calling an Integer converter with a String default, or any converter with a default whose runtime class is not assignable to the declared target type.

Common situations: Copy-paste of default values across converters of different types; generic helper passing an Object default into a typed converter.

Related errors


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