{"record":{"id":"4368053dda47abb9","repo":"hibernate/hibernate-orm","slug":"jdbc-type-code-s-s-not-known-to-have-a-corre","errorCode":null,"errorMessage":"JDBC type-code [%s (%s)] not known to have a corresponding LOB equivalent, and Java type is not Serializable (to use BLOB)","messagePattern":"JDBC type-code \\[(.+?) \\((.+?)\\)\\] not known to have a corresponding LOB equivalent, and Java type is not Serializable \\(to use BLOB\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java","lineNumber":774,"sourceCode":"\t\t\t\tmetadata.getTypeConfiguration().getJdbcTypeRegistry()\n\t\t\t\t\t\t.getDescriptor( jdbcTypeCode( recommendedJdbcType, domainJavaType ) ),\n\t\t\t\tjpaAttributeConverter\n\t\t);\n\t}\n\n\tprivate <T> int jdbcTypeCode(JdbcType recommendedJdbcType, JavaType<T> domainJavaType) {\n\t\tfinal int recommendedDdlTypeCode = recommendedJdbcType.getDdlTypeCode();\n\t\tfinal int jdbcTypeCode;\n\t\tif ( isLob() ) {\n\t\t\tif ( isMappedToKnownLobCode( recommendedDdlTypeCode ) ) {\n\t\t\t\tjdbcTypeCode = getLobCodeTypeMapping( recommendedDdlTypeCode );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif ( Serializable.class.isAssignableFrom( domainJavaType.getJavaTypeClass() ) ) {\n\t\t\t\t\tjdbcTypeCode = Types.BLOB;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\t\tLocale.ROOT,\n\t\t\t\t\t\t\t\t\t\"JDBC type-code [%s (%s)] not known to have a corresponding LOB equivalent, and Java type is not Serializable (to use BLOB)\",\n\t\t\t\t\t\t\t\t\trecommendedDdlTypeCode,\n\t\t\t\t\t\t\t\t\tJdbcTypeNameMapper.getTypeName( recommendedDdlTypeCode )\n\t\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tjdbcTypeCode = recommendedDdlTypeCode;\n\t\t}\n\t\treturn isNationalized() ? toNationalizedTypeCode( jdbcTypeCode ) : jdbcTypeCode;\n\t}\n\n\tpublic boolean isTypeSpecified() {\n\t\treturn typeName != null;","sourceCodeStart":756,"sourceCodeEnd":792,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/mapping/SimpleValue.java#L756-L792","documentation":"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.","triggerScenarios":"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).","commonSituations":"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).","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."],"exampleFix":"// before\n@Lob\nprivate Instant createdOn;  // Instant is not Serializable and TIMESTAMP has no LOB form\n\n// after\n@Column(name = \"created_on\")\nprivate Instant createdOn;","handlingStrategy":"type-guard","validationCode":"// before applying @Lob, check the Java type is either LOB-mappable or Serializable\nstatic boolean lobSafe(Class<?> javaType) {\n    return Serializable.class.isAssignableFrom(javaType)\n        || CharSequence.class.isAssignableFrom(javaType)\n        || javaType == byte[].class || javaType == char[].class;\n}\n// usage: assert lobSafe(field.getType()) before registering mappings","typeGuard":"static boolean supportsLobMapping(Class<?> javaType) {\n    return Serializable.class.isAssignableFrom(javaType)\n            || CharSequence.class.isAssignableFrom(javaType)\n            || javaType.isArray(); // byte[]/char[] have LONGVARBINARY/LONGVARCHAR equivalents\n}","tryCatchPattern":"try {\n    sf = new Configuration().addAnnotatedClass(Entity.class).buildSessionFactory();\n} catch (IllegalArgumentException | MappingException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"not known to have a corresponding LOB equivalent\")) {\n        throw new IllegalStateException(\"@Lob is unsupported for this property type; remove @Lob or make the type Serializable\", e);\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["hibernate","lob","jdbc-type","orm-mapping","type-resolution"],"backgroundTag":"unsupported-jdbc-type-mapping","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}