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

  1. 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)
  2. 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
  3. Check your Quarkus version; if the type is a standard scalar and still fails, report a Quarkus issue with the failing class
  4. 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

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


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