{"record":{"id":"6d99e550e4a52491","repo":"hibernate/hibernate-orm","slug":"error-attempting-to-apply-attributeconverter","errorCode":null,"errorMessage":"Error attempting to apply AttributeConverter","messagePattern":"Error attempting to apply AttributeConverter","errorType":"exception","errorClass":"PersistenceException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/AttributeConverterBean.java","lineNumber":103,"sourceCode":"\t\t\t\t? new AttributeConverterMutabilityPlan<>( this, true )\n\t\t\t\t: (MutabilityPlan<O>) mutabilityPlan;\n\t}\n\n\t@Override\n\tpublic ManagedBean<? extends AttributeConverter<O, R>> getConverterBean() {\n\t\treturn attributeConverterBean;\n\t}\n\n\t@Override\n\tpublic O toDomainValue(R relationalForm) {\n\t\ttry {\n\t\t\treturn attributeConverterBean.getBeanInstance().convertToEntityAttribute( relationalForm );\n\t\t}\n\t\tcatch (PersistenceException pe) {\n\t\t\tthrow pe;\n\t\t}\n\t\tcatch (RuntimeException re) {\n\t\t\tthrow new PersistenceException( \"Error attempting to apply AttributeConverter\", re );\n\t\t}\n\t}\n\n\t@Override\n\tpublic R toRelationalValue(O domainForm) {\n\t\ttry {\n\t\t\treturn attributeConverterBean.getBeanInstance().convertToDatabaseColumn( domainForm );\n\t\t}\n\t\tcatch (PersistenceException pe) {\n\t\t\tthrow pe;\n\t\t}\n\t\tcatch (RuntimeException re) {\n\t\t\tthrow new PersistenceException( \"Error attempting to apply AttributeConverter: \" + re.getMessage(), re );\n\t\t}\n\t}\n\n\t@Override\n\tpublic JavaType<? extends AttributeConverter<O, R>> getConverterJavaType() {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/AttributeConverterBean.java#L85-L121","documentation":"Hibernate wraps any non-PersistenceException RuntimeException thrown by your jakarta.persistence.AttributeConverter.convertToEntityAttribute while materializing an entity attribute from the database value. This variant is thrown from AttributeConverterBean, the wrapper used when the converter is resolved as a managed bean (CDI/Spring). The original exception is preserved as the cause, so the real failure is one level down.","triggerScenarios":"An entity attribute annotated @Convert (or covered by an auto-applied @Converter) whose converter class is obtained through the bean manager; loading the entity, and convertToEntityAttribute(relationalForm) throws a RuntimeException (NPE on null column, NumberFormatException on dirty data, IllegalArgumentException on an unrecognized code).","commonSituations":"Legacy rows containing values the converter cannot parse (old enum codes, empty strings, nulls not guarded); a schema/driver change making the JDBC value arrive as a different type (Integer vs String); migrating to Hibernate 6/7 where converter type checking became stricter; converter relying on injected beans that are null in the Hibernate module path.","solutions":["Read the cause: catch PersistenceException and inspect getCause() to find the converter line that failed","Make convertToEntityAttribute defensive: handle null input and unknown values explicitly (return null, throw an informative exception, or map to a default)","Cleanse or migrate offending column data so every stored value is convertible","If the JDBC type changed, fix the converter's declared relational type to match what the driver actually returns"],"exampleFix":"// before\n@Override\npublic Status convertToEntityAttribute(String dbValue) {\n    return Status.valueOf(dbValue); // throws on null/unknown code\n}\n// after\n@Override\npublic Status convertToEntityAttribute(String dbValue) {\n    if (dbValue == null || dbValue.isBlank()) {\n        return null;\n    }\n    try {\n        return Status.valueOf(dbValue);\n    }\n    catch (IllegalArgumentException e) {\n        throw new IllegalStateException(\"Unknown status code in DB: \" + dbValue, e);\n    }\n}","handlingStrategy":"try-catch","validationCode":"// before loading: sanity-check known raw values if you control the query\nList<String> bad = jdbcTemplate.queryForList(\"select distinct status from t_order\", String.class)\n        .stream().filter(v -> v != null && Status.tryParse(v) == null).toList();\nif (!bad.isEmpty()) throw new IllegalStateException(\"Unconvertible codes: \" + bad);","typeGuard":"// guard the converter itself against unexpected input\nstatic Status safeParse(String dbValue) {\n    if (dbValue == null) return null;\n    try { return Status.valueOf(dbValue); }\n    catch (IllegalArgumentException e) { return null; }\n}","tryCatchPattern":"try {\n    Order order = session.find(Order.class, id);\n} catch (PersistenceException e) {\n    if (e.getCause() instanceof IllegalArgumentException iae) {\n        // converter rejected a stored value: log column + value, quarantine row\n        log.warn(\"Unconvertible stored value: {}\", iae.getMessage());\n    } else { throw e; }\n}","preventionTips":["Unit-test every converter with null and every domain constant/relational value","Never let converters call valueOf/parse on unvalidated DB data without try/catch","Add DB check constraints so only values the converter knows can be stored","Wrap converter bodies so domain failures carry the offending value in the message"],"tags":["hibernate","orm","jpa","attribute-converter","persistence-exception","entity-loading"],"backgroundTag":"jpa-attribute-converter-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}