{"record":{"id":"1ceb9b4a88af5ee1","repo":"quarkusio/quarkus","slug":"unable-to-handle-temporal-type-paramtype","errorCode":null,"errorMessage":"Unable to handle temporal type '${paramType}'","messagePattern":"Unable to handle temporal type '(.+?)'","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java","lineNumber":655,"sourceCode":"        } else if (LOCAL_DATE_TIME.equals(paramType)) {\n            return new LocalDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName);\n        } else if (LOCAL_TIME.equals(paramType)) {\n            return new LocalTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName);\n        } else if (OFFSET_DATE_TIME.equals(paramType)) {\n            return new OffsetDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName);\n        } else if (OFFSET_TIME.equals(paramType)) {\n            return new OffsetTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName);\n        } else if (ZONED_DATE_TIME.equals(paramType)) {\n            return new ZonedDateTimeParamConverter.Supplier(format, dateTimeFormatterProviderClassName);\n        } else if (YEAR.equals(paramType)) {\n            return new YearParamConverter.Supplier(format, dateTimeFormatterProviderClassName);\n        } else if (YEAR_MONTH.equals(paramType)) {\n            return new YearMonthParamConverter.Supplier(format, dateTimeFormatterProviderClassName);\n        } else if (PERIOD.equals(paramType)) {\n            return new PeriodParamConverter.Supplier();\n        }\n\n        throw new RuntimeException(\n                contextualizeErrorMessage(\"Unable to handle temporal type '\" + paramType + \"'\", currentMethodInfo));\n    }\n\n    private void validateMethodsForInjectableBean(ClassInfo currentClassInfo) {\n        // do not check methods of records, they get the annotations from their record components, but that's automatic:\n        // they are actually placed on the constructor parameters and also end up on the fields and methods\n        if (currentClassInfo.isRecord()) {\n            return;\n        }\n        for (MethodInfo method : currentClassInfo.methods()) {\n            for (AnnotationInstance annotation : method.annotations()) {\n                if (annotation.target().kind() == AnnotationTarget.Kind.METHOD) {\n                    for (DotName annotationForField : JAX_RS_ANNOTATIONS_FOR_FIELDS) {\n                        if (annotation.name().equals(annotationForField)) {\n                            throw new DeploymentException(String.format(\n                                    \"Method '%s' of class '%s' is annotated with @%s annotation which is prohibited. \"\n                                            + \"Classes used as @BeanParam parameters must have a JAX-RS parameter annotation on \"\n                                            + \"fields only.\",","sourceCodeStart":637,"sourceCodeEnd":673,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java#L637-L673","documentation":"determineTemporalConverter maps a fixed set of java.time types (LocalDate, LocalDateTime, LocalTime, OffsetDateTime, OffsetTime, ZonedDateTime, YearMonth, Period, Instant) to built-in param converters. Any other type (Duration, ZoneId, Month, java.util.Date, custom temporals) fails deployment with this RuntimeException.","triggerScenarios":"A temporal/convert position parameter of an unsupported type, e.g. @QueryParam(\"ttl\") Duration ttl or @QueryParam(\"month\") Month month where no converter branch matches.","commonSituations":"Assuming all java.time types are supported; migrating from frameworks where Duration-style query params worked; using java.util.Date where the reactive stack expects temporal types.","solutions":["Change the parameter to a supported temporal type (LocalDate, LocalDateTime, LocalTime, OffsetDateTime, OffsetTime, ZonedDateTime, YearMonth, Period, Instant).","For Duration-like types, accept String and parse manually (Duration.parse) or register a custom ParamConverter.","Compare the paramType in the message against the supported branches in ServerEndpointIndexer."],"exampleFix":"// before\n@QueryParam(\"ttl\")\n@DateFormat(format = \"HH:mm\")\nDuration ttl;\n\n// after\n@QueryParam(\"ttl\")\nString ttl; // then Duration.parse(ttl) in the handler","handlingStrategy":"type-guard","validationCode":"static final Set<Class<?>> SUPPORTED_TEMPORAL = Set.of(\n    LocalDate.class, LocalDateTime.class, LocalTime.class, OffsetDateTime.class,\n    OffsetTime.class, ZonedDateTime.class, YearMonth.class, Period.class,\n    java.time.Instant.class);\nstatic boolean isSupportedTemporal(Class<?> t) { return SUPPORTED_TEMPORAL.contains(t); }","typeGuard":null,"tryCatchPattern":"try {\n    startQuarkus();\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unable to handle temporal type\")) {\n        log.error(\"Switch to a supported java.time type: \" + e.getMessage());\n    } else { throw e; }\n}","preventionTips":["Restrict temporal endpoint parameters to the documented supported set.","Use String parameters plus explicit parsing for exotic time types.","Check ServerEndpointIndexer's supported types when adding new time params.","Add deployment smoke tests to CI."],"tags":["resteasy-reactive","quarkus","java-time","temporal","param-converter","deployment-failure"],"backgroundTag":"unsupported-temporal-param-type","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}