oracle/graal · error · IllegalArgumentException

Unsupported annotation error element: %s

Error message

Unsupported annotation error element: %s

What it means

While converting individual annotation element values to the JDK proxy's expected forms, HostAnnotationValueConverter handles the known error-element kinds (MissingType -> TypeNotPresentExceptionProxy, ElementTypeMismatch -> DeferredAnnotationTypeMismatchExceptionProxy) but throws on any other ErrorElement subclass. The JDK annotation handler can only defer errors via specific proxies, so unrecognized error payloads cannot be represented and are rejected.

Source

Thrown at compiler/src/jdk.graal.compiler.vmaccess/src/jdk/graal/compiler/vmaccess/HostAnnotationValueConverter.java:141

            memberValues.put(memberName, annotationValueElementAsHostValue(member, member.getReturnType(), memberValue, typeToClass));
        }
        return annotationType.cast(AnnotationParser.annotationForMap(annotationType, memberValues));
    }

    /**
     * Converts one JVMCI annotation element representation to the value expected by the JDK
     * annotation invocation handler.
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    private static Object annotationValueElementAsHostValue(Method member, Class<?> targetType, Object value, Function<ResolvedJavaType, Class<?>> typeToClass) {
        if (value instanceof MissingType missingType) {
            return new TypeNotPresentExceptionProxy(missingType.getTypeName(), missingType.getCause());
        }
        if (value instanceof ElementTypeMismatch mismatch) {
            return new DeferredAnnotationTypeMismatchExceptionProxy(member, mismatch.getFoundType());
        }
        if (value instanceof ErrorElement) {
            throw new IllegalArgumentException("Unsupported annotation error element: " + value);
        }
        if (targetType.isArray()) {
            Class<?> componentType = targetType.getComponentType();
            List<?> elements = (List<?>) value;
            Object array = Array.newInstance(componentType, elements.size());
            for (int i = 0; i < elements.size(); i++) {
                Object element = annotationValueElementAsHostValue(member, componentType, elements.get(i), typeToClass);
                if (element instanceof ExceptionProxy) {
                    return element;
                }
                Array.set(array, i, element);
            }
            return array;
        }
        if (targetType == Class.class) {
            ResolvedJavaType classType = (ResolvedJavaType) value;
            Class<?> clazz = typeToClass.apply(classType);
            if (clazz == null) {

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Ensure the JVMCI provider only emits MissingType or ElementTypeMismatch error elements (or none).
  2. Filter ErrorElement-valued members (or replace with MissingType) before conversion if your consumer can tolerate their absence.
  3. Align the producer's ErrorElement vocabulary with the converter version you run against.
  4. If introducing a new ErrorElement kind, add a corresponding ExceptionProxy mapping in the converter first.

Example fix

// before: elements.put("value", new GenericErrorElement(...));
// after: elements.put("value", new MissingType(typeName, cause));
Defensive patterns

Strategy: validation

Validate before calling

Object v = elements.get(member);
if (v instanceof ErrorElement && !(v instanceof MissingType) && !(v instanceof ElementTypeMismatch)) {
    // replace or drop the member before conversion
}

Type guard

static boolean isSupportedErrorElement(Object v) { return v instanceof MissingType || v instanceof ElementTypeMismatch; }

Try / catch

try { convertElement(member, target, value, fn); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unsupported annotation error element")) { /* drop member or degrade gracefully */ } else throw e; }

Prevention

When it happens

Trigger: A JVMCI implementation (or replay data) puts an ErrorElement subclass other than MissingType/ElementTypeMismatch into an annotation's element map, and conversion of that member reaches annotationValueElementAsHostValue.

Common situations: Custom or experimental JVMCI providers introducing new ErrorElement kinds; deserialized/replayed annotation metadata containing legacy or future error markers; partial-classloading states recorded into snapshots.

Related errors


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