{"record":{"id":"5ee26272ea2f1ecb","repo":"FasterXML/jackson-databind","slug":"cannot-update-map-entry-values","errorCode":null,"errorMessage":"Cannot update Map.Entry values","messagePattern":"Cannot update Map\\.Entry values","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/tools/jackson/databind/deser/jdk/MapEntryDeserializer.java","lineNumber":311,"sourceCode":"            if (t == JsonToken.PROPERTY_NAME) { // most likely\n                ctxt.reportInputMismatch(this,\n                        \"Problem binding JSON into Map.Entry: more than one entry in JSON (second field: '%s')\",\n                        p.currentName());\n            } else {\n                // how would this occur?\n                ctxt.reportInputMismatch(this,\n                        \"Problem binding JSON into Map.Entry: unexpected content after JSON Object entry: \"+t);\n            }\n            return null;\n        }\n        return new AbstractMap.SimpleEntry<Object,Object>(key, value);\n    }\n\n    @Override\n    public Map.Entry<Object,Object> deserialize(JsonParser p, DeserializationContext ctxt,\n            Map.Entry<Object,Object> result) throws JacksonException\n    {\n        throw new IllegalStateException(\"Cannot update Map.Entry values\");\n    }\n\n    @Override\n    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,\n            TypeDeserializer typeDeserializer)\n        throws JacksonException\n    {\n        // In future could check current token... for now this should be enough:\n        return typeDeserializer.deserializeTypedFromObject(p, ctxt);\n    }\n\n    /*\n    /**********************************************************************\n    /* Alternate handlers\n    /**********************************************************************\n     */\n\n    /**","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/FasterXML/jackson-databind/blob/87876ca5c0569b4933aec2d30d6225e4b9ba3a43/src/main/java/tools/jackson/databind/deser/jdk/MapEntryDeserializer.java#L293-L329","documentation":"Map.Entry values are treated as immutable by the default MapEntryDeserializer; the three-argument deserialize(p, ctxt, resultToUpdate) override unconditionally throws IllegalStateException. Jackson's 'update/merge' API (readerForUpdating, updateValue) requires the deserializer to support in-place updates, which a single-entry key/value pair cannot do meaningfully.","triggerScenarios":"Calling objectMapper.readerForUpdating(existingEntry).readValue(json) where the target is a Map.Entry; invoking mapper.updateValue(entry, jsonNode) with a Map.Entry instance; using ObjectReaderToUpdate patterns against a Map.Entry-typed property.","commonSituations":"Treating Map.Entry as a mutable POJO; migrating code that used a Pair-like class to Map.Entry; JSON patch/merge APIs applied to entry types; frameworks that generically call updateValue on every field type.","solutions":["Replace Map.Entry with a mutable pair type (e.g. AbstractMap.SimpleEntry, or a custom Pair class with setters).","Deserialize into a fresh Map.Entry each time instead of updating an existing one.","If merging is required, deserialize to a Map and construct a new entry from the merged result."],"exampleFix":"// before\nMap.Entry<String,Integer> entry = ...;\nentry = mapper.readerForUpdating(entry).readValue(json); // throws\n\n// after\nAbstractMap.SimpleEntry<String,Integer> entry = ...;\nentry = mapper.readerForUpdating(new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue())).readValue(json);","handlingStrategy":"try-catch","validationCode":"if (target instanceof Map.Entry && operation == UPDATE) {\n    throw new UnsupportedOperationException(\n        \"Map.Entry is immutable; use AbstractMap.SimpleEntry for updates\");\n}","typeGuard":"boolean isUpdatablePairType(Class<?> c) {\n    return c != null\n        && !Map.Entry.class.isAssignableFrom(c);\n}","tryCatchPattern":"try {\n    mapper.readerForUpdating(entry).readValue(json);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Map.Entry\")) {\n        // fall back to fresh deserialization\n        entry = mapper.readValue(json, new TypeReference<Map.Entry<K,V>>(){});\n    } else throw e;\n}","preventionTips":["Use AbstractMap.SimpleEntry (or a custom Pair) whenever you need readerForUpdating/updateValue.","Static-check that no Map.Entry-typed field is passed to updateValue.","Document immutability of Map.Entry in domain model guides."],"tags":["deserialization","map-entry","update-value","immutability","illegal-state"],"backgroundTag":null,"analyzedSha":"87876ca5c0569b4933aec2d30d6225e4b9ba3a43","analyzedAt":"2026-08-11T12:55:24.033Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}