{"record":{"id":"e66e7192b75436c3","repo":"hibernate/hibernate-orm","slug":"unsupported-temporal-type-s","errorCode":null,"errorMessage":"Unsupported temporal type: %s","messagePattern":"Unsupported temporal type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/function/SpannerFormatFunction.java","lineNumber":39,"sourceCode":" */\npublic class SpannerFormatFunction extends FormatFunction {\n\tpublic SpannerFormatFunction(TypeConfiguration typeConfiguration) {\n\t\tsuper(\"format_timestamp\", true, true, false, typeConfiguration);\n\t}\n\n\t@Override\n\tpublic void render(\n\t\t\tSqlAppender sqlAppender,\n\t\t\tList<? extends SqlAstNode> sqlAstArguments,\n\t\t\tReturnableType<?> returnType,\n\t\t\tSqlAstTranslator<?> walker) {\n\t\tvar datetime = (Expression) sqlAstArguments.get( 0 );\n\t\tvar format = sqlAstArguments.get( 1 );\n\t\tvar temporalType = getSqlTemporalType( datetime.getExpressionType() );\n\t\tswitch ( temporalType ) {\n\t\t\tcase DATE -> sqlAppender.appendSql( \"format_date(\" );\n\t\t\tcase TIME, TIMESTAMP -> sqlAppender.appendSql( \"format_timestamp(\" );\n\t\t\tdefault -> throw new IllegalArgumentException( \"Unsupported temporal type: \" + temporalType );\n\t\t}\n\t\tformat.accept( walker );\n\t\tsqlAppender.append( ',' );\n\t\tdatetime.accept( walker );\n\t\tsqlAppender.append( ')' );\n\t}\n}\n","sourceCodeStart":21,"sourceCodeEnd":47,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/function/SpannerFormatFunction.java#L21-L47","documentation":"Spanner's format() rendering picks format_date vs format_timestamp from the first argument's temporal type. DATE, TIME and TIMESTAMP are handled; anything else — offset or zoned temporal types (OffsetDateTime, ZonedDateTime, OffsetTime) or a null type — reaches the default branch and throws IllegalArgumentException during SQL rendering.","triggerScenarios":"HQL: format(e.offsetTs, 'YYYY-MM-DD') on the Cloud Spanner dialect, where the attribute is mapped as OffsetDateTime/ZonedDateTime/OffsetTime.","commonSituations":"Entities shared between Spanner and other databases; mapping audit timestamps as OffsetDateTime by convention; adopting the Spanner dialect on an existing model.","solutions":["Cast the argument to a plain timestamp: format(cast(e.offsetTs as timestamp), ...)","Map the attribute as LocalDateTime (or Instant per project convention) for Spanner","Upgrade Hibernate — Spanner temporal type coverage improves across releases"],"exampleFix":"// before\nselect format(e.offsetTs, 'YYYY-MM') from Event e\n\n// after\nselect format(cast(e.offsetTs as timestamp), 'YYYY-MM') from Event e","handlingStrategy":"type-guard","validationCode":"// Spanner format() only accepts DATE/TIME/TIMESTAMP-mapped expressions\nstatic void checkSpannerFormatArg(Class<?> attrType) {\n    if (OffsetDateTime.class.equals(attrType) || ZonedDateTime.class.equals(attrType)\n            || OffsetTime.class.equals(attrType)) {\n        throw new IllegalArgumentException(\"Cast offset/zoned temporals to timestamp for Spanner: \" + attrType);\n    }\n}","typeGuard":"static boolean spannerTemporalSafe(Class<?> t) {\n    return !(OffsetDateTime.class.equals(t) || ZonedDateTime.class.equals(t) || OffsetTime.class.equals(t));\n}","tryCatchPattern":"try {\n    return em.createQuery(hql, String.class).getResultList();\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Unsupported temporal type\")) {\n        return em.createQuery(withTimestampCast(hql), String.class).getResultList();\n    }\n    throw e;\n}","preventionTips":["Map Spanner entities with LocalDate/LocalDateTime/LocalTime, not offset types","Wrap risky expressions in cast(... as timestamp) when porting models","Add an integration test that formats every temporal attribute on Spanner"],"tags":["hibernate","spanner","format-function","temporal-type","dialect-limitation"],"backgroundTag":"temporal-type-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}