FasterXML/jackson-databind · error · IllegalArgumentException

Cannot pass null modifier

Error message

Cannot pass null modifier

What it means

Thrown by DeserializerFactoryConfig.withDeserializerModifier(ValueDeserializerModifier) when the argument is null. Jackson forbids registering a null deserializer modifier because modifiers are stored in an array and must be resolvable, so a null entry would break iteration during deserializer construction. It fails fast at registration time rather than later during deserialization.

Solutions

  1. Guard the call site: only invoke withDeserializerModifier(modifier) when modifier != null.
  2. If you intended a no-op, pass a ValueDeserializerModifier whose methods delegate to the default instead of null.
  3. Check that the expression producing the modifier (factory method, DI lookup) never returns null.

Example fix

// before
config.withDeserializerModifier(maybeModifier());

// after
ValueDeserializerModifier m = maybeModifier();
if (m != null) {
    config.withDeserializerModifier(m);
}
Defensive patterns

Strategy: validation

Validate before calling

ValueDeserializerModifier modifier = resolveModifier();
if (modifier == null) {
    // skip or log; do not call withDeserializerModifier(null)
} else {
    config.withDeserializerModifier(modifier);
}

Prevention

When it happens

Trigger: Calling mapperBuilder or a Module's setupModule with DeserializerFactoryConfig.withDeserializerModifier(null), or passing a null ValueDeserializerModifier when constructing a custom DeserializerFactory configuration. Also triggered indirectly if a module registers a modifier that resolves to null.

Common situations: Writing a custom JacksonModule that conditionally adds a modifier and forgets the null guard; wiring a SimpleModule's addDeserializerModifier(null); refactoring that leaves a null where a lambda/anonymous modifier was expected.

Related errors


AI-assisted analysis of FasterXML/jackson-databind@87876ca5c0 (2026-08-11). Data as JSON: /api/errors/b3ed26598ebb3893. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/tools/jackson/databind/cfg/DeserializerFactoryConfig.java:125

    {
        if (additional == null) {
            throw new IllegalArgumentException("Cannot pass null KeyDeserializers");
        }
        KeyDeserializers[] all = ArrayBuilders.insertInListNoDup(_additionalKeyDeserializers, additional);
        return new DeserializerFactoryConfig(_additionalDeserializers, all, _modifiers,
                _valueInstantiators);
    }

    /**
     * Fluent/factory method used to construct a configuration object that
     * has same configuration as this instance plus one additional
     * deserialiazer modifier. Added modifier has the highest priority (that is, it
     * gets called before any already registered modifier).
     */
    public DeserializerFactoryConfig withDeserializerModifier(ValueDeserializerModifier modifier)
    {
        if (modifier == null) {
            throw new IllegalArgumentException("Cannot pass null modifier");
        }
        ValueDeserializerModifier[] all = ArrayBuilders.insertInListNoDup(_modifiers, modifier);
        return new DeserializerFactoryConfig(_additionalDeserializers, _additionalKeyDeserializers,
                all, _valueInstantiators);
    }

    /**
     * Fluent/factory method used to construct a configuration object that
     * has same configuration as this instance plus specified additional
     * value instantiator provider object.
     * Added instantiator provider has the highest priority (that is, it
     * gets called before any already registered resolver).
     *
     * @param instantiators Object that can provide {@link tools.jackson.databind.deser.ValueInstantiator}s for
     *    constructing POJO values during deserialization
     */
    public DeserializerFactoryConfig withValueInstantiators(ValueInstantiators instantiators)
    {

View on GitHub (pinned to 87876ca5c0)