hibernate/hibernate-orm · error · IllegalArgumentException
Can't render value because java type is null
Error message
Can't render value because java type is null
What it means
When an SQM tree is rendered back to HQL (query-plan cache keys, diagnostics, criteria-to-HQL display), SqmLiteral.appendHqlString stringifies a non-null value through its JavaType. If the literal was constructed without a type (null JavaType), rendering is impossible and it throws IllegalArgumentException('Can't render value because java type is null').
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/expression/SqmLiteral.java:94
}
@Override
public String asLoggableText() {
return "Literal( " + getLiteralValue() + ")";
}
@Override
public void appendHqlString(StringBuilder hql, SqmRenderContext context) {
appendHqlString( hql, getJavaTypeDescriptor(), getLiteralValue() );
}
public static <T> void appendHqlString(StringBuilder sb, @Nullable JavaType<T> javaType, @Nullable T value) {
if ( value == null ) {
sb.append( "null" );
}
else {
if ( javaType == null ) {
throw new IllegalArgumentException( "Can't render value because java type is null" );
}
if ( value instanceof Number || value instanceof Boolean ) {
// We know these are safe to render
sb.append( value );
}
else if ( value instanceof Enum<?> enumValue ) {
sb.append( enumValue.getDeclaringClass().getTypeName() ).append( "." ).append( enumValue.name() );
}
else {
// Even if this is not 100% correct, our goal with this implementation is to provide
// a cache key or insight into the query structure, not necessarily produce an executable query
appendSingleQuoteEscapedString( sb, javaType.toString( value ) );
}
}
}
@Override
public boolean equals(@Nullable Object object) {View on GitHub (pinned to fad1729dce)
Solutions
- Create literals through nodeBuilder().literal(value), which resolves the JavaType automatically.
- When constructing SqmLiteral manually, always pass a non-null type, e.g. nodeBuilder().getTypeConfiguration().getBasicTypeForJavaType(value.getClass()).
- In custom nodes, initialize the type eagerly (setExpressibleType) before the query is rendered.
Example fix
// before new SqmLiteral<>( value, null, nodeBuilder ); // appendHqlString later -> IllegalArgumentException // after nodeBuilder.literal( value ); // or new SqmLiteral<>( value, nodeBuilder.getTypeConfiguration().getBasicTypeForJavaType( value.getClass() ), nodeBuilder );
Defensive patterns
Strategy: validation
Validate before calling
JavaType<?> jt = literal.getJavaTypeDescriptor();
if ( literal.getLiteralValue() != null && jt == null ) {
throw new IllegalStateException( "literal has no JavaType - rebuild it via nodeBuilder().literal(value)" );
} Prevention
- Use nodeBuilder().literal(...) instead of constructing SqmLiteral by hand.
- Never pass a null inherent type when creating literal nodes.
- In custom SQM nodes, set the expressible type eagerly before the query is rendered.
When it happens
Trigger: Constructing SqmLiteral (or a subclass) directly with a null SqmTypedNode/inherent type but a non-null value - new SqmLiteral<>(value, null, nodeBuilder) - and then triggering HQL rendering via createQuery, tree copy, or logging; also custom SqmExpression implementations whose getNodeType()/getJavaTypeDescriptor() returns null.
Common situations: Custom SQM node subclasses with lazy or missing types; literals created while a query is half-built; tree copies that drop type information; Hibernate upgrades changing when literal types get attached.
Related errors
- Informix does not support binary literals
- Unable to determine JavaType to use : {}
- Entity discriminator cannot be de-referenced
- Could not build SqmPathSource for entity identifier: {}
- Entity discriminator cannot be de-referenced
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/95eb2f60b465c9f9.
Report an issue: GitHub.