FasterXML/jackson-databind · error · InvalidFormatException
`DeserializationProblemHandler.handleNullForPrimitives()`…
Error message
`DeserializationProblemHandler.handleNullForPrimitives()` for type %s returned value of type %s
What it means
Thrown by DeserializationContext.handleNullForPrimitives() when a registered DeserializationProblemHandler returns a non-null value for a null-to-primitive coercion but that value's type is incompatible with the target primitive type. Jackson validates the handler's return value via _isCompatible() to catch buggy handlers early, since silent type mismatches on primitives would cause confusing downstream errors.
Solutions
- Ensure your handleNullForPrimitives() returns a value whose type matches or is a wrapper of the targetClass parameter (e.g., return Integer 0 for int targetClass).
- Return DeserializationProblemHandler.NOT_HANDLED if your handler cannot handle the specific case, letting other handlers or the default behavior take over.
- Add a type check in your handler: if (!targetClass.isInstance(myDefault)) return NOT_HANDLED; before returning.
Example fix
// before
@Override
public Object handleNullForPrimitives(DeserializationContext ctxt, Class<?> targetType,
JsonParser p, ValueDeserializer<?> deser, String msg) {
return "0"; // wrong: String is not compatible with int
}
// after
@Override
public Object handleNullForPrimitives(DeserializationContext ctxt, Class<?> targetType,
JsonParser p, ValueDeserializer<?> deser, String msg) {
if (targetType == int.class) return 0;
return NOT_HANDLED;
} Defensive patterns
Strategy: validation
Validate before calling
// Validate handler return type before returning
@Override
public Object handleNullForPrimitives(DeserializationContext ctxt, Class<?> targetType,
JsonParser p, ValueDeserializer<?> deser, String msg) {
Object candidate = computeDefault(targetType);
if (candidate != null && !targetType.isInstance(candidate)
&& !(targetType.isPrimitive() && ClassUtil.wrapperType(targetType).isInstance(candidate))) {
return DeserializationProblemHandler.NOT_HANDLED; // let default handle it
}
return candidate;
} Type guard
boolean isHandlerValueCompatible(Class<?> target, Object value) {
if (value == null || target.isInstance(value)) return true;
return target.isPrimitive() && ClassUtil.wrapperType(target).isInstance(value);
} Prevention
- Return NOT_HANDLED from your handler when unsure of type compatibility.
- Match the handler return type exactly to the targetClass wrapper.
- Unit-test the handler for each primitive type it may encounter.
When it happens
Trigger: Registering a custom DeserializationProblemHandler that overrides handleNullForPrimitives() and returns a value that is not assignable to the target primitive's wrapper type. For example, the handler returns a String "0" when the target is int, or returns a Long when the target is a double field (though wrapper compatibility is checked for primitives).
Common situations: Custom problem handlers designed to supply defaults for null primitives that return the wrong Java type. Handlers returning null explicitly (which is allowed). Handlers returning domain objects instead of primitive-compatible values.
Related errors
- maxProblems must be positive, was
- AnnotationIntrospector returned `Class<
- AnnotationIntrospector returned Class
- AnnotationIntrospector returned Class
- AnnotationIntrospector returned Converter definition of type
AI-assisted analysis of FasterXML/jackson-databind@87876ca5c0 (2026-08-11).
Data as JSON: /api/errors/69a081b17d10de67.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/tools/jackson/databind/DeserializationContext.java:1575
*/
public Object handleNullForPrimitives(Class<?> targetClass,
JsonParser p, ValueDeserializer<?> deser,
String msgTemplate, Object... msgArgs)
throws JacksonException
{
// but if not handled, just throw exception
LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
String msg = _format(msgTemplate, msgArgs);
while (h != null) {
// Can bail out if it's handled
Object instance = h.value().handleNullForPrimitives(this, targetClass, p, deser, msg);
if (instance != DeserializationProblemHandler.NOT_HANDLED) {
// Sanity check for broken handlers, otherwise nasty to debug:
if (_isCompatible(targetClass, instance)) {
return instance;
}
// In case our problem handler providing incompatible value,
throw new InvalidFormatException(_parser,
"`DeserializationProblemHandler.handleNullForPrimitives()` for type %s returned value of type %s".formatted(
ClassUtil.nameOf(targetClass), ClassUtil.getClassDescription(instance)),
instance, targetClass
);
}
h = h.next();
}
return reportInputMismatch(deser, msg);
}
/**
* Method that deserializers should call if they fail to instantiate value
* due to lack of viable instantiator (usually creator, that is, constructor
* or static factory method). Method should be called at point where value
* has not been decoded, so that handler has a chance to handle decoding
* using alternate mechanism, and handle underlying content (possibly by
* just skipping it) to keep input state valid
*
* @param instClass Type that was to be instantiatedView on GitHub (pinned to 87876ca5c0)