{"record":{"id":"5c51711e293134b7","repo":"hibernate/hibernate-orm","slug":"couldn-t-determine-basic-type-for-java-type-5c5171","errorCode":null,"errorMessage":"Couldn't determine basic type for java type: {}","messagePattern":"Couldn't determine basic type for java type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmExpression.java","lineNumber":165,"sourceCode":"\t\t\t// safe cast, because we just checked\n\t\t\t@SuppressWarnings(\"unchecked\")\n\t\t\tfinal SqmExpression<X> castExpression = (SqmExpression<X>) this;\n\t\t\treturn castExpression;\n\t\t}\n\t\telse {\n\t\t\tfinal QueryEngine queryEngine = nodeBuilder().getQueryEngine();\n\t\t\tfinal SqmCastTarget<?> target = new SqmCastTarget<>( (ReturnableType<?>) type, nodeBuilder() );\n\t\t\treturn queryEngine.getSqmFunctionRegistry().getFunctionDescriptor( \"cast\" )\n\t\t\t\t\t.generateSqmExpression( asList( this, target ), (ReturnableType<X>) type, queryEngine );\n\t\t}\n\t}\n\n\t@Nonnull\n\t@Override\n\tdefault <X> SqmExpression<X> cast(@Nonnull Class<X> type) {\n\t\tfinal BasicType<X> basicType = nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType( type );\n\t\tif ( basicType == null ) {\n\t\t\tthrow new IllegalArgumentException( \"Couldn't determine basic type for java type: \" + type.getName() );\n\t\t}\n\t\treturn castAs( basicType );\n\t}\n\n\t@Nonnull\n\t@Override\n\tJpaPredicate notEqualTo(@Nonnull Expression<?> value);\n\n\t@Nonnull\n\t@Override\n\tJpaPredicate notEqualTo(Object value);\n}\n","sourceCodeStart":147,"sourceCodeEnd":178,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmExpression.java#L147-L178","documentation":"SqmExpression.cast(Class) resolves the target Java type through the session's TypeConfiguration via getBasicTypeForJavaType(). Only classes with a registered BasicType can serve as cast targets; for anything else (entity classes, embeddables, interfaces, arbitrary POJOs, unregistered custom types) Hibernate cannot build a cast expression and throws IllegalArgumentException naming the class.","triggerScenarios":"Calling expression.cast(X.class) where X has no registered basic type: casting to an entity or embeddable class, to Object or Serializable, to an array type, to a custom value class without @JavaTypeRegistration/@Converter mapping, or to a java.time/jdbc type the current dialect does not register.","commonSituations":"Cast targets chosen dynamically at runtime (the Class comes from a variable or user input); attempts to widen an expression by casting to Object; custom types registered only for specific dialects or lost during refactors; Hibernate upgrades where a formerly registered default type disappeared.","solutions":["Cast to a standard basic type instead (String, Integer, Long, Double, BigDecimal, Boolean, dates).","Resolve the BasicType explicitly and use castAs(): BasicType<X> t = nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType(X.class); if non-null, call expr.castAs(t).","Register a JavaType/BasicType for the class globally with @JavaTypeRegistration (or map it with an AttributeConverter) so the lookup succeeds.","For entity types use treatAs()/type() constructs rather than cast()."],"exampleFix":"// before\nSqmExpression<Money> e = expr.cast( Money.class ); // no BasicType for Money -> IllegalArgumentException\n\n// after - resolve the registered basic type and cast with it\nBasicType<Money> moneyType = nodeBuilder().getTypeConfiguration()\n        .getBasicTypeForJavaType( Money.class );\nSqmExpression<Money> e = expr.castAs( moneyType ); // register the type first if moneyType == null","handlingStrategy":"validation","validationCode":"BasicType<X> basicType = nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType( type );\nif ( basicType == null ) {\n    throw new IllegalArgumentException( \"No basic type registered for \" + type.getName()\n            + \" - cast to a standard type or register a @JavaTypeRegistration\" );\n}\nreturn expr.castAs( basicType );","typeGuard":"static boolean isCastableToBasicType(NodeBuilder nb, Class<?> javaType) {\n    return nb.getTypeConfiguration().getBasicTypeForJavaType( javaType ) != null;\n}","tryCatchPattern":null,"preventionTips":["Whitelist cast targets to known basic types (String, numeric wrappers, temporal types).","Register custom value classes with @JavaTypeRegistration or an AttributeConverter before casting to them.","Use castAs(BasicType) after an explicit lookup instead of cast(Class) when the target is dynamic."],"tags":["hibernate","sqm","cast","basic-type","type-configuration","criteria-api"],"backgroundTag":"unknown-type-cast","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}