hibernate/hibernate-orm · error · IllegalArgumentException
JDBC type-code [%s (%s)] not known to have a corresponding L
Error message
JDBC type-code [%s (%s)] not known to have a corresponding LOB equivalent, and Java type is not Serializable (to use BLOB)
What it means
Thrown while SimpleValue resolves the JDBC type code for a @Lob/@Nationalized-lob mapped attribute. When the value is marked as a LOB, Hibernate maps the recommended DDL type code to its LOB variant (e.g. VARCHAR to LONGVARCHAR/CLOB). If the recommended code (like TIMESTAMP for java.time.Instant, or DATE) has no LOB equivalent, the only escape hatch is BLOB serialization — allowed only when the Java type implements Serializable. When neither condition holds, this IllegalArgumentException is thrown.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java:774
metadata.getTypeConfiguration().getJdbcTypeRegistry()
.getDescriptor( jdbcTypeCode( recommendedJdbcType, domainJavaType ) ),
jpaAttributeConverter
);
}
private <T> int jdbcTypeCode(JdbcType recommendedJdbcType, JavaType<T> domainJavaType) {
final int recommendedDdlTypeCode = recommendedJdbcType.getDdlTypeCode();
final int jdbcTypeCode;
if ( isLob() ) {
if ( isMappedToKnownLobCode( recommendedDdlTypeCode ) ) {
jdbcTypeCode = getLobCodeTypeMapping( recommendedDdlTypeCode );
}
else {
if ( Serializable.class.isAssignableFrom( domainJavaType.getJavaTypeClass() ) ) {
jdbcTypeCode = Types.BLOB;
}
else {
throw new IllegalArgumentException(
String.format(
Locale.ROOT,
"JDBC type-code [%s (%s)] not known to have a corresponding LOB equivalent, and Java type is not Serializable (to use BLOB)",
recommendedDdlTypeCode,
JdbcTypeNameMapper.getTypeName( recommendedDdlTypeCode )
)
);
}
}
}
else {
jdbcTypeCode = recommendedDdlTypeCode;
}
return isNationalized() ? toNationalizedTypeCode( jdbcTypeCode ) : jdbcTypeCode;
}
public boolean isTypeSpecified() {
return typeName != null;View on GitHub (pinned to fad1729dce)
Solutions
- Remove @Lob from the non-LOB-mappable attribute and control length/precision with @Column(length=...), @JdbcTypeCode, or the dialect default.
- If serialized storage is acceptable, make the attribute's Java type implement java.io.Serializable so the BLOB fallback applies.
- For Strings needing unlimited length use @JdbcTypeCode(SqlTypes.LONGVARCHAR) or @Column(columnDefinition="clob") instead of forcing LOB on a temporal/UUID type.
- Verify with MetadataBuilder + SchemaExport in a test so the mapping fails at build time with a clear location.
Example fix
// before @Lob private Instant createdOn; // Instant is not Serializable and TIMESTAMP has no LOB form // after @Column(name = "created_on") private Instant createdOn;
Defensive patterns
Strategy: type-guard
Validate before calling
// before applying @Lob, check the Java type is either LOB-mappable or Serializable
static boolean lobSafe(Class<?> javaType) {
return Serializable.class.isAssignableFrom(javaType)
|| CharSequence.class.isAssignableFrom(javaType)
|| javaType == byte[].class || javaType == char[].class;
}
// usage: assert lobSafe(field.getType()) before registering mappings Type guard
static boolean supportsLobMapping(Class<?> javaType) {
return Serializable.class.isAssignableFrom(javaType)
|| CharSequence.class.isAssignableFrom(javaType)
|| javaType.isArray(); // byte[]/char[] have LONGVARBINARY/LONGVARCHAR equivalents
} Try / catch
try {
sf = new Configuration().addAnnotatedClass(Entity.class).buildSessionFactory();
} catch (IllegalArgumentException | MappingException e) {
if (e.getMessage() != null && e.getMessage().contains("not known to have a corresponding LOB equivalent")) {
throw new IllegalStateException("@Lob is unsupported for this property type; remove @Lob or make the type Serializable", e);
}
throw e;
} Prevention
- Only use @Lob on String, byte[], char[], Clob/Blob, or Serializable types.
- Never put @Lob on java.time.*, UUID, or enums unless they are Serializable and you want BLOB serialization.
- Cover SessionFactory bootstrap with a schema-export test to catch type resolution early.
When it happens
Trigger: Annotating a field of a non-Serializable, non-LOB-mappable type with @Lob — typical examples: @Lob on java.time.Instant, java.time.LocalDate, java.util.UUID mapped to a non-SqlType, or an enum mapped to INTEGER — then triggering type resolution (SessionFactory bootstrap or schema export).
Common situations: Developers add @Lob hoping for unlimited length on temporal or UUID columns; upgrading Hibernate where previously the type silently resolved; mapping custom value types that don't implement Serializable with @Lob; combining @Lob with @JdbcTypeCode(Types.TIMESTAMP).
Related errors
- Attribute types for a dynamicEntity must be explicitly speci
- JDBC type-code [%s (%s)] not known to have a corresponding L
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4368053dda47abb9.
Report an issue: GitHub.