{"record":{"id":"763bd73dc3c1a695","repo":"hibernate/hibernate-orm","slug":"key-cannot-be-null-or-empty","errorCode":null,"errorMessage":"key cannot be null or empty","messagePattern":"key cannot be null or empty","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/format/StringJsonDocumentWriter.java","lineNumber":108,"sourceCode":"\t\tthis.appender.append( StringJsonDocumentMarker.ARRAY_START.getMarkerCharacter() );\n\t\treturn this;\n\t}\n\n\t/**\n\t * Callback to be called when the end of an array is encountered.\n\t */\n\t@Override\n\tpublic JsonDocumentWriter endArray() {\n\t\tthis.appender.append( StringJsonDocumentMarker.ARRAY_END.getMarkerCharacter() );\n\t\tthis.processingStates.push( JsonProcessingState.ENDING_ARRAY );\n\t\tmoveProcessingStateMachine();\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic JsonDocumentWriter objectKey(String key) {\n\t\tif ( key == null || key.isEmpty() ) {\n\t\t\tthrow new IllegalArgumentException( \"key cannot be null or empty\" );\n\t\t}\n\n\t\tif ( JsonProcessingState.OBJECT.equals( this.processingStates.getCurrent() ) ) {\n\t\t\t// we have started an object, and we are adding an item key: we do add a separator.\n\t\t\tthis.appender.append( StringJsonDocumentMarker.SEPARATOR.getMarkerCharacter() );\n\t\t}\n\t\tthis.appender.append( StringJsonDocumentMarker.QUOTE.getMarkerCharacter() );\n\t\tthis.appender.append( key );\n\t\tthis.appender.append( \"\\\":\" );\n\t\tmoveProcessingStateMachine();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Adds a separator if needed.\n\t * The logic here is know if we have to prepend a separator\n\t * as such, it must be called at the beginning of all methods\n\t * Separator is to separate array items or key/value pairs in an object.","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/format/StringJsonDocumentWriter.java#L90-L126","documentation":"StringJsonDocumentWriter.objectKey(String) emits a \"key\": pair while building the JSON document and refuses null or empty keys with an IllegalArgumentException. Hibernate reaches this while serializing a Java map or embeddable into a JSON column: an entry whose key (or attribute name) is null or the empty string cannot be represented as a JSON object member.","triggerScenarios":"Flushing an entity whose JSON-mapped field contains a null or \"\" key: @JdbcTypeCode(SqlTypes.JSON) Map<String, Object> with a null/empty key entry, dynamic-map entities with a null map key, or any custom JsonDocumentWriter client calling objectKey(null)/objectKey(\"\").","commonSituations":"Maps built from user input or Collectors.groupingBy(...) with null keys persisted as JSON; a HashMap with its single permitted null key sneaking in; map keys trimmed/generated into empty strings.","solutions":["Sanitize map keys before persisting: drop or rename null/empty entries (e.g. replace null with \"\")","Validate in a @PrePersist/@PreUpdate listener or in the entity setter so bad maps never reach the writer","If a null key must be represented, encode it as a sentinel string like \"__null__\"","Catch IllegalArgumentException at flush to identify the offending entity and field"],"exampleFix":"// before\nentity.setAttributes(userMap); // userMap contains null or \"\" keys -> flush fails\n// after\nMap<String, Object> safe = new LinkedHashMap<>();\nuserMap.forEach((k, v) -> {\n    if (k != null && !k.isEmpty()) safe.put(k, v);\n});\nentity.setAttributes(safe);","handlingStrategy":"validation","validationCode":"static Map<String, Object> sanitizeKeys(Map<String, Object> map) {\n    Map<String, Object> out = new java.util.LinkedHashMap<>();\n    map.forEach((k, v) -> {\n        if (k == null || k.isEmpty()) return; // or remap: out.put(\"__null__\", v)\n        out.put(k, v);\n    });\n    return out;\n}\n\nentity.setAttributes(sanitizeKeys(rawMap));","typeGuard":"static boolean isValidJsonKey(String key) {\n    return key != null && !key.isEmpty();\n}","tryCatchPattern":"try {\n    session.persist(entity);\n    session.flush();\n} catch (IllegalArgumentException e) {\n    if (\"key cannot be null or empty\".equals(e.getMessage())) {\n        throw new ValidationException(\"JSON map keys must be non-empty strings\", e);\n    }\n    throw e;\n}","preventionTips":["Validate map keys at the entity setter - reject null/empty before flush","Use groupingBy collectors with a null-safe key mapper","Add a @PrePersist/@PreUpdate listener that scans JSON-mapped maps for invalid keys"],"tags":["hibernate","json","serialization","validation","map-key"],"backgroundTag":"invalid-argument","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}