quarkusio/quarkus · error · UnsupportedOperationException

The `{instance.name}` annotation can only be used in methods

Error message

The `{instance.name}` annotation can only be used in methods or classes.

What it means

Quarkus keys Jackson features (@JsonView, @CustomSerialization, @CustomDeserialization) by a target identifier computed from the annotation's target: class, method, or method parameter (request body). If the annotation is placed on any other target — most commonly a field — no identifier can be built and the deployment fails with this UnsupportedOperationException naming the annotation class.

Source

Thrown at extensions/resteasy-reactive/rest-jackson/deployment/src/main/java/io/quarkus/resteasy/reactive/jackson/deployment/processor/ResteasyReactiveJacksonProcessor.java:722

                    .asParameterizedType()
                    .arguments()
                    .stream()
                    .anyMatch(t -> fieldTypeHasSecureFields(t, indexView, typeToHasSecureField, needToDeleteCache));
        }
        return false;
    }

    private String getTargetId(AnnotationInstance instance) {
        AnnotationTarget target = instance.target();
        if (target.kind() == AnnotationTarget.Kind.CLASS) {
            return getClassId(target.asClass());
        } else if (target.kind() == AnnotationTarget.Kind.METHOD) {
            return getMethodId(target.asMethod());
        } else if (target.kind() == AnnotationTarget.Kind.METHOD_PARAMETER) {
            return "request-body;" + getMethodId(target.asMethodParameter().method());
        }

        throw new UnsupportedOperationException(String.format("The `%s` annotation can only "
                + "be used in methods or classes.", instance.name()));
    }

    private String getClassId(ClassInfo classInfo) {
        return classInfo.name().toString();
    }

    private String getMethodId(MethodInfo methodInfo) {
        return getMethodId(methodInfo, methodInfo.declaringClass());
    }

    private String getMethodId(MethodInfo methodInfo, ClassInfo declaringClassInfo) {
        List<String> parameterClassNames = new ArrayList<>(methodInfo.parametersCount());
        for (Type parameter : methodInfo.parameterTypes()) {
            parameterClassNames.add(parameter.name().toString());
        }
        return MethodId.get(methodInfo.name(), declaringClassInfo.name().toString(),
                parameterClassNames.toArray(EMPTY_STRING_ARRAY));

View on GitHub (pinned to e1c734241f)

Solutions

  1. Move the annotation from the field to the JAX-RS resource method (or resource class) that returns/consumes the DTO
  2. For per-field view filtering, keep @JsonView on DTO fields (plain Jackson handles that) and reference the view classes via @JsonView on the resource method only
  3. Ensure you import com.fasterxml.jackson.annotation.JsonView and apply it only on the resource endpoints for Quarkus REST features
  4. If you intended request-body customization, annotate the method parameter instead

Example fix

// before
class Resource {
    @JsonView(Public.class) // wrong: on a field of the resource
    private User user;
}

// after
class Resource {
    @GET
    @JsonView(Public.class)
    public User get() { ... }
}
Defensive patterns

Strategy: type-guard

Validate before calling

for (AnnotatedElement e : annotatedElements) {
    if ((e instanceof Field) && e.isAnnotationPresent(JsonView.class))
        throw new IllegalStateException("@JsonView on a field of a resource class is not supported; move it to the method");
}

Type guard

static boolean isSupportedTarget(AnnotatedElement el) {
    return el instanceof java.lang.reflect.Method || el instanceof Class<?> || isMethodParameter(el);
}

Try / catch

try {
    deploy();
} catch (UnsupportedOperationException e) {
    if (e.getMessage() != null && e.getMessage().contains("can only be used in methods or classes")) {
        // relocate the annotation named in the message
    }
}

Prevention

When it happens

Trigger: Putting @JsonView (or @CustomSerialization/@CustomDeserialization) on a field, enum constant, or other non class/method/parameter element of a JAX-RS resource class.

Common situations: Habit from plain Jackson where @JsonView is commonly used on fields/properties; migrating a Spring or standard-Jackson DTO annotation set onto Quarkus REST resources; accidental import of the wrong @JsonView annotation placed at field level in the resource class.

Related errors


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