hibernate/hibernate-orm · error · IllegalArgumentException
Unsupported temporal type: %s
Error message
Unsupported temporal type: %s
What it means
Spanner's trunc() routing maps DATE to DATE_TRUNC and TIMESTAMP/TIME to TIMESTAMP_TRUNC; other temporal types (offset/zoned timestamps) have no Spanner function and hit the default branch, throwing IllegalArgumentException at render time. A null temporal type falls through to numeric trunc, which is fine.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/SpannerTruncFunction.java:53
)
);
}
@Override
public void render(
SqlAppender sqlAppender,
List<? extends SqlAstNode> sqlAstArguments,
ReturnableType<?> returnType,
SqlAstTranslator<?> walker) {
final Expression expression = (Expression) sqlAstArguments.get( 0 );
final var type = expression.getExpressionType();
final var temporalType = type != null ? getSqlTemporalType( type ) : null;
if ( temporalType != null ) {
switch ( temporalType ) {
case DATE -> sqlAppender.appendSql( "DATE_TRUNC" );
case TIMESTAMP, TIME -> sqlAppender.appendSql( "TIMESTAMP_TRUNC" );
default -> throw new IllegalArgumentException( "Unsupported temporal type: " + temporalType );
}
sqlAppender.appendSql( "(" );
expression.accept( walker );
sqlAppender.appendSql( ", " );
sqlAstArguments.get( 1 ).accept( walker );
sqlAppender.appendSql( ")" );
}
else {
renderNumericTrunc( sqlAppender, sqlAstArguments, walker );
}
}
private void renderNumericTrunc(
SqlAppender sqlAppender,
List<? extends SqlAstNode> args,
SqlAstTranslator<?> walker) {
sqlAppender.appendSql( "TRUNC(" );
args.get( 0 ).accept( walker );View on GitHub (pinned to fad1729dce)
Solutions
- Cast the argument: trunc(cast(e.offsetTs as timestamp), MONTH)
- Remap the attribute to LocalDateTime for Spanner
- Upgrade Hibernate for wider Spanner temporal coverage
Example fix
// before select trunc(e.offsetTs, MONTH) from Event e // after select trunc(cast(e.offsetTs as timestamp), MONTH) from Event e
Defensive patterns
Strategy: type-guard
Validate before calling
// Spanner trunc() only accepts DATE/TIME/TIMESTAMP expressions
static void checkSpannerTruncArg(Class<?> attrType) {
if (OffsetDateTime.class.equals(attrType) || ZonedDateTime.class.equals(attrType)
|| OffsetTime.class.equals(attrType)) {
throw new IllegalArgumentException("Cast offset/zoned temporals to timestamp for Spanner: " + attrType);
}
} Type guard
static boolean spannerTemporalSafe(Class<?> t) {
return !(OffsetDateTime.class.equals(t) || ZonedDateTime.class.equals(t) || OffsetTime.class.equals(t));
} Try / catch
try {
return em.createQuery(hql, Object.class).getResultList();
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("Unsupported temporal type")) {
return em.createQuery(withTimestampCast(hql), Object.class).getResultList();
}
throw e;
} Prevention
- Avoid offset/zoned temporal mappings on Spanner entities
- Bucket offset timestamps only after an explicit cast to timestamp
- Keep a Spanner-dialect integration test for every date-math query
When it happens
Trigger: HQL: trunc(OffsetDateTime-attribute) or trunc(ZonedDateTime-attribute) on the Cloud Spanner dialect.
Common situations: Date-bucketing queries (day/week/month rollups) over attributes mapped as offset/zoned types; models ported to Spanner without remapping temporal attributes.
Related errors
- Unsupported temporal type: %s
- Temporal unit not supported [%s]
- HSQLDB only supports the case insensitive flag 'i' as litera
- Can't emulate filter clause for inverse distribution functio
- Can't emulate filter clause for inverse distribution functio
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/01efe7d177597c1d.
Report an issue: GitHub.