{"record":{"id":"57ee9c7c6ddf3de9","repo":"hibernate/hibernate-orm","slug":"unsupported-temporal-type-temporalaccessor-g","errorCode":null,"errorMessage":"\"Unsupported temporal type: \" + temporalAccessor.getClass().getName()","messagePattern":"\"Unsupported temporal type: \" \\+ temporalAccessor\\.getClass\\(\\)\\.getName\\(\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/dialect/SpannerPostgreSQLDialect.java","lineNumber":635,"sourceCode":"\t\t\tTemporalType precision,\n\t\t\tTimeZone jdbcTimeZone) {\n\t\tif ( precision == TemporalType.TIME || (precision == TemporalType.TIMESTAMP && !temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS ))) {\n\t\t\tprecision = TemporalType.TIMESTAMP;\n\t\t\tif ( temporalAccessor instanceof LocalTime localTime) {\n\t\t\t\ttemporalAccessor = localTime.atDate( LocalDate.of( 1970, 1, 1 ) )\n\t\t\t\t\t\t.atOffset( ZoneOffset.UTC );\n\t\t\t}\n\t\t\telse if ( temporalAccessor instanceof OffsetTime offsetTime ) {\n\t\t\t\ttemporalAccessor = offsetTime.atDate( LocalDate.of( 1970, 1, 1 ) );\n\t\t\t}\n\t\t\telse if ( temporalAccessor instanceof LocalDateTime localDateTime) {\n\t\t\t\ttemporalAccessor = localDateTime.atOffset(  ZoneOffset.UTC );\n\t\t\t}\n\t\t\telse if ( temporalAccessor instanceof Instant instant) {\n\t\t\t\ttemporalAccessor = instant.atOffset(  ZoneOffset.UTC );\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new UnsupportedOperationException( \"Unsupported temporal type: \" + temporalAccessor.getClass().getName() );\n\t\t\t}\n\t\t}\n\n\t\tsuper.appendDateTimeLiteral(  appender, temporalAccessor, precision, jdbcTimeZone );\n\t}\n\n\t@Override\n\tpublic void appendDateTimeLiteral(\n\t\t\tSqlAppender appender,\n\t\t\tDate date,\n\t\t\t@SuppressWarnings(\"deprecation\")\n\t\t\tTemporalType precision,\n\t\t\tTimeZone jdbcTimeZone) {\n\t\tif ( precision == TemporalType.TIME ) {\n\t\t\tprecision = TemporalType.TIMESTAMP;\n\t\t}\n\t\tsuper.appendDateTimeLiteral( appender, date, precision, jdbcTimeZone );\n\t}","sourceCodeStart":617,"sourceCodeEnd":653,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/dialect/SpannerPostgreSQLDialect.java#L617-L653","documentation":"SpannerPostgreSQLDialect.appendDateTimeLiteral(TemporalAccessor, ...) throws UnsupportedOperationException when the literal must be normalized (precision is TIME, or TIMESTAMP without an offset — i.e. !isSupported(ChronoField.OFFSET_SECONDS)) but the value is not one of LocalTime, OffsetTime, LocalDateTime, or Instant. The dialect needs an OffsetDateTime-shaped literal for Spanner PG's timestamptz semantics; exotic TemporalAccessor implementations (Year, YearMonth, MonthDay, non-ISO chronologies like JapaneseDate, or a LocalDate fed through the TIME/TIMESTAMP path) cannot be converted, so it names the offending class and throws.","triggerScenarios":"Passing a temporal literal parameter that is a non-ISO-chronology date (e.g. JapaneseDate/ThaiBuddhistDate), java.time.Year/YearMonth/MonthDay, or a LocalDate under TemporalType.TIME, as a query parameter bound for literal rendering: `q.setParameter(\"d\", value)` with rendering as a datetime literal on SpannerPostgreSQLDialect.","commonSituations":"Locale-aware apps using non-ISO calendars (Japanese era dates) persisted through Hibernate; APIs that accept broad TemporalAccessor-typed fields and forward them to queries; mapping a LocalDate attribute with @Temporal(TemporalType.TIME) by mistake; JDBC drivers that hand back non-standard temporal implementations.","solutions":["Normalize parameters to supported types before binding: convert LocalDate/Year/YearMonth → LocalDate or LocalDateTime, ZonedDateTime → Instant/OffsetDateTime, non-ISO dates → LocalDate.atTime(...) via LocalDate.from(temporal).","If the field is a date, map it as LocalDate (no @Temporal) so the TIME/TIMESTAMP literal path is not taken.","Convert non-ISO chronology values with `LocalDate.from(temporalAccessor)` at the API boundary.","As a last resort, format the value to a String and parse it in SQL (cast(... as timestamptz)) instead of binding a TemporalAccessor."],"exampleFix":"// before\nTemporalAccessor v = JapaneseDate.now(); // non-ISO, unsupported\nq.setParameter(\"d\", v);\n\n// after\nq.setParameter(\"d\", LocalDate.from(v)); // normalized to supported type","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static OffsetDateTime toSpannerLiteral(TemporalAccessor t) {\n  if (t instanceof Instant i) return i.atOffset(ZoneOffset.UTC);\n  if (t instanceof LocalDateTime ldt) return ldt.atOffset(ZoneOffset.UTC);\n  if (t instanceof OffsetDateTime odt) return odt;\n  if (t instanceof ZonedDateTime zdt) return zdt.toOffsetDateTime();\n  if (t instanceof LocalDate ld) return ld.atStartOfDay(ZoneOffset.UTC).toOffsetDateTime();\n  if (t instanceof LocalTime lt) return lt.atDate(LocalDate.EPOCH).atOffset(ZoneOffset.UTC);\n  if (t instanceof OffsetTime ot) return ot.atDate(LocalDate.EPOCH);\n  throw new IllegalArgumentException(\"Unsupported temporal type for Spanner PG literal: \" + t.getClass().getName());\n}","tryCatchPattern":"try {\n  q.setParameter(\"d\", value).getResultList();\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().startsWith(\"Unsupported temporal type:\")) {\n    q.setParameter(\"d\", LocalDate.from(value)).getResultList(); // normalize and retry\n  } else throw e;\n}","preventionTips":["Bind java.time types Spanner PG handles (Instant, OffsetDateTime, LocalDateTime, LocalTime, LocalDate) instead of raw TemporalAccessor.","Convert non-ISO chronology values (JapaneseDate etc.) with LocalDate.from(...) at the API boundary.","Never map date fields with @Temporal(TemporalType.TIME).","Type query parameters concretely; avoid TemporalAccessor in repository signatures."],"tags":["hibernate","cloud-spanner","spanner-postgresql","temporal","java-time","query-parameter","unsupportedoperationexception"],"backgroundTag":"unsupported-temporal-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}