Skip to content

JsonMapper.Builder.modules(...) ignores changes after build() due to internal saveState #5481

@libetl

Description

@libetl

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

When using JsonMapper.Builder to create multiple mappers, calling modules(a, b, c, d).build(); then modules(e, f, g, h).build(); will always register only the first set (a, b, c, d) in both mappers, even though the builder API appears mutable. The internal 'saveStateApplyModules' in MapperBuilder prevents subsequent changes from taking effect after the first build(). This is misleading and dangerous: the expectation is that the builder’s current configuration is used with each build(), but instead, changes to modules(...) after the initial build() are ignored.

This breaks dev expectations around Builder API predictability, can lead to silent and confusing bugs, and forces all users to create new Builder instances for every configuration — even if they want only a minor difference. Ideally, the API should either throw a ConfigurationException on reused builders, or else reliably reflect the latest modules provided to modules(...).

Version Information

Jackson 3.0.0 and 3.1.x (tested on 3.1.2)

Reproduction

Minimal Kotlin snippet:

val builder = JsonMapper.Builder().modules(a, b, c, d)
val m1 = builder.build()
val m2 = builder.modules(e, f, g, h).build()
println(m2.registeredModules()) 
// outputs a, b, c, d
// (should output a, b, c, d, e, f, g, h)
// (or should fail)

Expected: m2 should register only e, f, g, h.
Actual: m2 registers the initial modules from first build().

Expected behavior

Expected:

  • subsequent calls to modules(...) after build() should reflect the latest modules in each new build()
  • Or: changing modules after build() should throw a ConfigurationException (fail fast) to avoid subtle bugs

Actual:

  • Only the initial configuration 'sticks', later calls are silently ignored
  • leads to wasted debugging time and accidental misconfiguration

Additional context

This is a major pitfall for anyone using the JsonMapper Builder to create slightly different configurations, e.g. when your company uses different PropertyNamingStrategies accross the org. The API appears mutable and chainable, so the current behavior violates least-surprise and causes buggy production deployments.

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.0Issue planned for initial 3.0 release

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions