{"record":{"id":"6e05e72e6dd2bdac","repo":"FasterXML/jackson-databind","slug":"cannot-set-maxdeserializercachesize-to-a-negative","errorCode":null,"errorMessage":"Cannot set maxDeserializerCacheSize to a negative value","messagePattern":"Cannot set maxDeserializerCacheSize to a negative value","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/cfg/DefaultCacheProvider.java","lineNumber":166,"sourceCode":"         * Corresponds to {@link DefaultCacheProvider#_maxTypeFactoryCacheSize}.\n         */\n        private int _maxTypeFactoryCacheSize = TypeFactory.DEFAULT_MAX_CACHE_SIZE;\n\n        Builder() { }\n\n        /**\n         * Define the maximum size of the {@link LookupCache} instance constructed by {@link #forDeserializerCache(DeserializationConfig)}\n         * and {@link #_buildCache(int)}.\n         * <p>\n         * Note that specifying a maximum size of zero prevents values from being retained in the cache.\n         *\n         * @param maxDeserializerCacheSize Size for the {@link LookupCache} to use within {@link DeserializerCache}\n         * @return this builder\n         * @throws IllegalArgumentException if {@code maxDeserializerCacheSize} is negative\n         */\n        public Builder maxDeserializerCacheSize(int maxDeserializerCacheSize) {\n            if (maxDeserializerCacheSize < 0) {\n                throw new IllegalArgumentException(\"Cannot set maxDeserializerCacheSize to a negative value\");\n            }\n            _maxDeserializerCacheSize = maxDeserializerCacheSize;\n            return this;\n        }\n\n        /**\n         * Define the maximum size of the {@link LookupCache} instance constructed by {@link #forSerializerCache(SerializationConfig)}\n         * and {@link #_buildCache(int)}\n         * <p>\n         * Note that specifying a maximum size of zero prevents values from being retained in the cache.\n         *\n         * @param maxSerializerCacheSize Size for the {@link LookupCache} to use within {@link SerializerCache}\n         * @return this builder\n         * @throws IllegalArgumentException if {@code maxSerializerCacheSize} is negative\n         */\n        public Builder maxSerializerCacheSize(int maxSerializerCacheSize) {\n            if (maxSerializerCacheSize < 0) {\n                throw new IllegalArgumentException(\"Cannot set maxSerializerCacheSize to a negative value\");","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/a50c7d2a1d57234ac4adf70dbd88ac90db6436e4/src/main/java/tools/jackson/databind/cfg/DefaultCacheProvider.java#L148-L184","documentation":"DefaultCacheProvider.Builder.maxDeserializerCacheSize(int) sets the maximum number of entries the deserializer cache (DeserializerCache) may hold; zero disables caching but negative values are nonsensical, so the builder rejects them with IllegalArgumentException. The cache stores resolved ValueDeserializers keyed by type, so a negative cap would mean 'hold fewer than nothing', which is an internal-logic error rather than a tuning choice.","triggerScenarios":"Calling builder.maxDeserializerCacheSize(-1) (or any negative); computing the size from a property/expression that can go negative; passing -1 intending 'unlimited' (this builder has no unlimited sentinel — use a very large int or the default).","commonSituations":"A 'max cache' config where -1 was used to mean 'no limit' in another library but here means invalid; arithmetic (base - overhead) that underflows for small inputs; environment variable parsed with a default of -1 when unset.","solutions":["Use 0 to disable the cache, or a large positive int (e.g. Integer.MAX_VALUE or a documented high bound) for 'effectively unlimited'.","Validate the configured value at the configuration boundary: if (v < 0) throw new IllegalStateException(...).","Map any '-1 means unlimited' convention at the property-reading layer to a concrete large positive value before calling the builder.","Add a unit test asserting the builder rejects negatives and accepts 0 and large positives."],"exampleFix":"// before\nint cap = props.getInt(\"deser.cache.max\", -1); // -1 meant 'unlimited' in old lib\nDefaultCacheProvider provider = DefaultCacheProvider.builder()\n    .maxDeserializerCacheSize(cap).build(); // throws\n// after\nint cap = props.getInt(\"deser.cache.max\", -1);\nint safe = (cap < 0) ? Integer.MAX_VALUE : cap;\nDefaultCacheProvider provider = DefaultCacheProvider.builder()\n    .maxDeserializerCacheSize(safe).build();","handlingStrategy":"validation","validationCode":"int cap = configuredDeserCache;\nif (cap < 0) throw new IllegalArgumentException(\"deser cache < 0: \" + cap);\nDefaultCacheProvider.builder().maxDeserializerCacheSize(cap).build();","typeGuard":"// primitive int range check","tryCatchPattern":"try {\n    return DefaultCacheProvider.builder().maxDeserializerCacheSize(cap).build();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"negative\")) {\n        return DefaultCacheProvider.builder().maxDeserializerCacheSize(0).build();\n    }\n    throw e;\n}","preventionTips":["Validate cache-size config at the property boundary; map -1 to a large positive or 0.","Use 0 to disable caching intentionally; never pass a negative.","Document the chosen cache semantics in your config schema."],"tags":["cache","configuration","builder","validation"],"analyzedSha":"a50c7d2a1d57234ac4adf70dbd88ac90db6436e4","analyzedAt":"2026-08-06T20:31:51.404Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}