oracle/graal · error · IllegalArgumentException

Annotation member %s.%s does not match declared type %s

Error message

Annotation member %s.%s does not match declared type %s

What it means

AnnotationValueValidation.validateElements checks each explicit element of a JVMCI AnnotationValue against the declared member types of the corresponding annotation type; a member whose runtime value does not match its declared type (e.g. a String where an int/class/enum is declared, even recursively inside arrays) throws this with the annotation name, member name, and expected type. Per the javadoc, missing members and defaults are intentionally not checked — only present elements with the wrong kind of value.

Source

Thrown at compiler/src/jdk.graal.compiler.vmaccess/src/jdk/graal/compiler/vmaccess/AnnotationValueValidation.java:66

    }

    /**
     * Validates each explicitly supplied, recognized element of {@code annotationValue} against
     * the member type described by {@code annotationValueType}, recursively checking array
     * elements. Error elements are accepted because they represent failures that must remain
     * deferred until the affected annotation member is accessed. Missing members and defaults are
     * not checked here; providers preserve missing required members and supply defaults while
     * materializing the annotation proxy.
     *
     * @param annotationValue the annotation metadata containing the explicit elements
     * @param annotationValueType the declared member types used for validation
     * @throws IllegalArgumentException if an element does not match its declared member type
     */
    public static void validateElements(AnnotationValue annotationValue, AnnotationValueType annotationValueType) {
        for (Map.Entry<String, Object> entry : annotationValue.getElements().entrySet()) {
            ResolvedJavaType memberType = annotationValueType.memberTypes().get(entry.getKey());
            if (memberType != null && !matchesElementType(entry.getValue(), memberType)) {
                throw new IllegalArgumentException("Annotation member " + annotationValue.getAnnotationType().toJavaName() + "." + entry.getKey() +
                                " does not match declared type " + memberType.toJavaName());
            }
        }
    }

    /**
     * Determines whether a JVMCI annotation element representation matches its declared member
     * type, recursively validating array elements.
     */
    private static boolean matchesElementType(Object value, ResolvedJavaType expectedType) {
        if (value == null) {
            return false;
        }
        if (value instanceof ErrorElement) {
            return true;
        }
        if (expectedType.isArray()) {
            if (!(value instanceof List<?> elements)) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Fix the producer of the AnnotationValue so element values match declared member types (primitives boxed correctly, classes as ResolvedJavaType, enums as EnumElement, arrays as lists).
  2. If consuming foreign metadata, validate with this method early and reject/report the offending annotation before use.
  3. Align JVMCI/JDK versions between producer and consumer so member declarations agree.
  4. Log annotationValue.getAnnotationType().toJavaName() + member name at the failure site to pinpoint the bad member.

Example fix

// before: elements.put("phase", "Phase plat forming"); // String for enum member
// after: elements.put("phase", new EnumElement(CompilationPhasePhase, "PLATFORMING"));
Defensive patterns

Strategy: validation

Validate before calling

for (Map.Entry<String, Object> e : annotationValue.getElements().entrySet()) {
    ResolvedJavaType declared = annotationValueType.memberTypes().get(e.getKey());
    if (declared != null && !AnnotationValueValidation.matchesElementTypePublic(e.getValue(), declared)) {
        // report and drop the bad member before downstream conversion
    }
}

Try / catch

try { AnnotationValueValidation.validateElements(av, avt); } catch (IllegalArgumentException e) { /* log av.getAnnotationType().toJavaName() + member and reject the annotation */ }

Prevention

When it happens

Trigger: A JVMCI-returned annotation whose element map contains a value of an incompatible Java type for its declared member — class-valued member holding a String, array member holding a non-list, enum member holding a wrong-type constant — reaching validateElements. The recursive matchesElementType check also fails on null values or arrays containing mismatched elements.

Common situations: Hand-constructed or deserialized AnnotationValue metadata (e.g. from a snapshot/replay system or a custom JVMCI implementation) where element maps were built loosely; version skew where an annotation's members changed type between JVMCI versions.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/7e0f8d335ac77e44. Report an issue: GitHub.