quarkusio/quarkus · error · RuntimeException

Failed to find converter for ${elementType}

Error message

Failed to find converter for ${elementType}

What it means

During endpoint scanning, ServerEndpointIndexer.extractConverter must produce a ParameterConverter for each JAX-RS parameter type (e.g. @QueryParam/@PathParam values). If the element type has no built-in converter and existingConverters maps it to null (meaning no registered converter exists) and runtime converters are disabled, the deployment fails with 'Failed to find converter'.

Source

Thrown at independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/ServerEndpointIndexer.java:710

        // no converter if we have a RestForm mime type: this goes via message body readers in MultipartFormParamExtractor
        if (getPartMime(annotations) != null)
            return null;
        if (elementType.equals(String.class.getName())) {
            if (hasRuntimeConverters)
                return new RuntimeResolvedConverter.Supplier().setDelegate(new NoopParameterConverter.Supplier());
            // String needs no conversion
            return null;
        } else if (existingConverters.containsKey(elementType)) {
            String className = existingConverters.get(elementType);
            ParameterConverterSupplier delegate;
            if (className == null)
                delegate = null;
            else
                delegate = new LoadedParameterConverter().setClassName(className);
            if (hasRuntimeConverters)
                return new RuntimeResolvedConverter.Supplier().setDelegate(delegate);
            if (delegate == null)
                throw new RuntimeException("Failed to find converter for " + elementType);
            return delegate;
        } else if (elementType.equals(PathSegment.class.getName())) {
            return new PathSegmentParamConverter.Supplier();
        } else if (elementType.equals("char")) {
            return new CharParamConverter.Supplier();
        } else if (elementType.equals(Character.class.getName())) {
            return new CharacterParamConverter.Supplier();
        } else if (elementType.equals(FileUpload.class.getName())
                || elementType.equals(Path.class.getName())
                || elementType.equals(File.class.getName())
                || elementType.equals(InputStream.class.getName())
                || elementType.equals(EntityPart.class.getName())) {
            // this is handled by MultipartFormParamExtractor
            return null;
        } else {
            DotName typeName = DotName.createSimple(elementType);
            if (SUPPORT_TEMPORAL_PARAMS.contains(typeName)) {
                //It might be a LocalDate[Time] object

View on GitHub (pinned to e1c734241f)

Solutions

  1. Implement and register a javax.ws.rs.ext.ParamConverter/ParamConverterProvider for the custom type so it gets indexed at build time
  2. Annotate the parameter type with @ParamConverter (org.jboss.resteasy.reactive) or register the converter via a build-step/extension so it appears in existingConverters
  3. Change the parameter type to String and convert manually inside the method
  4. Enable runtime converters (quarkus.resteasy-reactive.enable-runtime-converter or the relevant @RuntimeConfig use) if the converter is only available at runtime

Example fix

// before
@GET
public String get(@QueryParam("color") Color color) {...} // no converter
// after
@Provider
public class ColorParamConverterProvider implements ParamConverterProvider {
  public <T> ParamConverter<T> getConverter(Class<T> raw, Type generic, Annotation[] anns) {
    if (raw == Color.class) return (ParamConverter<T>) new ColorParamConverter();
    return null;
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every custom JAX-RS param type has a registered ParamConverter
Set<Class<?>> used = Set.of(Color.class, Filter.class);
for (Class<?> t : used) {
  boolean hasConverter = converterProviderClasses.stream()
    .anyMatch(p -> p.getConverter(t, null, new Annotation[0]) != null);
  if (!hasConverter) throw new IllegalStateException("No ParamConverter registered for " + t.getName());
}

Try / catch

try {
  buildApplication();
} catch (RuntimeException e) {
  if (e.getMessage().startsWith("Failed to find converter for ")) {
    String type = e.getMessage().substring("Failed to find converter for ".length());
    log.error("Register a ParamConverter/ParamConverterProvider for " + type);
  }
  throw e;
}

Prevention

When it happens

Trigger: A resource method parameter (query, path, header, form, cookie) of a custom type T for which no ParamConverter/Converter class was registered and which is not String, char, PathSegment, temporal, multipart, or otherwise handled. The type previously had a converter indexed, but the map entry value is null and hasRuntimeConverters is false.

Common situations: Using a POJO or enum-like custom type as a @QueryParam without registering a ParamConverter; removing a ParamConverterProvider that previously handled the type; running in a mode where runtime converter lookup is disabled (native/generic build) so unindexed types cannot resolve.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/9b52776dae42bf25. Report an issue: GitHub.