quarkusio/quarkus · error · IllegalStateException
Type {fieldType} should be handled by the switch
Error message
Type {fieldType} should be handled by the switch What it means
During Quarkus's build-time generation of a custom Jackson deserializer, generated bytecode converts a JSON tree node into a primitive/simple-typed field value via a switch over the field's type name. The switch only covers String, char/Character, short/Short, int/Integer, long/Long, float/Float, double/Double and boolean/Boolean. If some other type reaches this primitive-conversion path, the deployment fails with an IllegalStateException, indicating an internal assumption was broken rather than a user-facing API misuse.
Source
Thrown at extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/JacksonDeserializerFactory.java:1112
case "int" ->
isValueNullFalse.invokeVirtualMethod(ofMethod(JsonNode.class, "asInt", int.class),
valueNode);
case "java.lang.Integer" ->
isValueNullFalse.invokeStaticMethod(ofMethod(Integer.class, "valueOf", Integer.class, int.class),
isValueNullFalse.invokeVirtualMethod(ofMethod(JsonNode.class, "asInt", int.class),
valueNode));
case "long", "java.lang.Long" ->
isValueNullFalse.invokeVirtualMethod(ofMethod(JsonNode.class, "asLong", long.class),
valueNode);
case "float", "java.lang.Float" -> isValueNullFalse
.convertPrimitive(
isValueNullFalse.invokeVirtualMethod(ofMethod(JsonNode.class, "asDouble", double.class), valueNode),
float.class);
case "double", "java.lang.Double" -> isValueNullFalse
.invokeVirtualMethod(ofMethod(JsonNode.class, "asDouble", double.class), valueNode);
case "boolean", "java.lang.Boolean" -> isValueNullFalse
.invokeVirtualMethod(ofMethod(JsonNode.class, "asBoolean", boolean.class), valueNode);
default -> throw new IllegalStateException("Type " + fieldType + " should be handled by the switch");
};
isValueNullFalse.assign(result, convertedValue);
return result;
}
@Override
protected Optional<MethodInfo> findConstructor(ClassInfo classInfo) {
Optional<MethodInfo> ctorOpt = super.findConstructor(classInfo);
if (ctorOpt.isPresent() && ctorOpt.get().parametersCount() == 0 && !classInfo.isRecord()) {
Set<String> unsettableFields = findUnsettableFields(classInfo);
if (!unsettableFields.isEmpty()) {
return classInfo.constructors().stream()
.filter(ctor -> Modifier.isPublic(ctor.flags()) && ctorCoversFields(ctor, unsettableFields))
.findFirst();
}
}View on GitHub (pinned to e1c734241f)
Solutions
- Inspect the field type named in the message and change it to a supported scalar (String, int/Integer, long/Long, double/Double, float/Float, boolean/Boolean, short/Short, char/Character)
- Convert unsupported scalar fields (e.g. byte/Byte, BigDecimal) to a supported type or use a plain Jackson deserializer (@JsonDeserialize/@JsonProperty with custom deserializer) instead of the generated one
- Check your Quarkus version; if the type is a standard scalar and still fails, report a Quarkus issue with the failing class
- Work around by disabling the generated custom deserialization (remove @CustomDeserialization / related config) so stock Jackson handles the type
Example fix
// before
class Dto { private byte flags; }
// after
class Dto { private int flags; } // or use a Jackson @JsonDeserialize on the field Defensive patterns
Strategy: validation
Validate before calling
Set<String> supported = Set.of("java.lang.String","char","java.lang.Character","short","java.lang.Short","int","java.lang.Integer","long","java.lang.Long","float","java.lang.Float","double","java.lang.Double","boolean","java.lang.Boolean");
for (Field f : Dto.class.getDeclaredFields()) {
if (!supported.contains(f.getType().getName()))
throw new IllegalStateException("Field " + f + " not supported by generated Jackson deserializer");
} Type guard
static boolean isSupportedScalar(Type t) {
String n = t.getTypeName();
return n.equals("java.lang.String") || n.equals("int") || n.equals("java.lang.Integer")
|| n.equals("long") || n.equals("java.lang.Long") || n.equals("double") || n.equals("java.lang.Double")
|| n.equals("float") || n.equals("java.lang.Float") || n.equals("boolean") || n.equals("java.lang.Boolean")
|| n.equals("short") || n.equals("java.lang.Short") || n.equals("char") || n.equals("java.lang.Character");
} Try / catch
try {
applicationResult = quarkusBuild();
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().contains("should be handled by the switch")) {
// fall back to stock Jackson deserialization for the offending DTO
}
} Prevention
- Keep DTO fields to common scalars and wrapper types
- Use standard Jackson annotations instead of generated custom (de)serializers for exotic types
- Run a full build after upgrading Quarkus to catch new gaps early
- Pin DTOs with unusual fields behind their own converters
When it happens
Trigger: A resource class field with a primitive/wrapper-ish type outside the supported set ends up on the primitive-field deserialization code path in JacksonDeserializerFactory (typically a byte/Byte, BigDecimal or similar field in a @CustomDeserialization-generated deserializer, or an internal regression).
Common situations: Using unusual field types like byte, Byte or java.math.BigDecimal in DTOs processed by the generated-deserializer feature; upgrading Quarkus and a previously working DTO trips a newly uncovered path; mixing Jackson custom serialization annotations with non-standard scalar field types.
Related errors
- 'quarkus-narayana-lra' can only work if 'quarkus-rest-jackso
- Type {type} should be handled by the switch
- Failed to open path tree with root %s
- Dev services for ${request.getName()} requires a startable s
- Name cannot start with '/':${name}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/7ec70c6763b9ce64.
Report an issue: GitHub.