oracle/graal · error · IllegalArgumentException

Annotation class element type %s has no host class

Error message

Annotation class element type %s has no host class

What it means

When an annotation member is declared as Class (Class<?> value()), the converter takes the ResolvedJavaType element value and maps it through the caller's typeToClass function; if that returns null, this exception names the class type that could not be mapped. It is the element-level analogue of error 395 — the annotation itself resolved, but a class-valued member refers to a type with no host class.

Source

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

        }
        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) {
                throw new IllegalArgumentException("Annotation class element type " + classType.toJavaName() + " has no host class");
            }
            return clazz;
        }
        if (targetType.isEnum()) {
            EnumElement enumElement = (EnumElement) value;
            Class<?> enumType = typeToClass.apply(enumElement.enumType);
            if (enumType == null) {
                throw new IllegalArgumentException("Annotation enum element type " + enumElement.enumType.toJavaName() + " has no host class");
            }
            if (enumType != targetType) {
                throw new IllegalArgumentException("Unexpected enum type: " + enumType.getName());
            }
            try {
                return Enum.valueOf((Class<? extends Enum>) enumType.asSubclass(Enum.class), enumElement.name);
            } catch (IllegalArgumentException e) {
                return new EnumConstantNotPresentExceptionProxy((Class<? extends Enum<?>>) enumType, enumElement.name);
            }
        }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Make typeToClass able to resolve the named type (extend its loader/search set; put the missing class on the classpath).
  2. For replay scenarios, record/provide host classes for all types referenced by class-valued annotation members.
  3. If unmappable class members are acceptable in your use, pre-scan elements and substitute a TypeNotPresentExceptionProxy-like deferral instead of converting.
  4. Log classType.toJavaName() from the catch site to identify exactly which class is missing.

Example fix

// before
Function<ResolvedJavaType, Class<?>> fn = t -> bootLoader.get(t.toJavaName()); // null for app classes
// after
Function<ResolvedJavaType, Class<?>> fn = t -> {
    Class<?> c = bootLoader.get(t.toJavaName());
    return c != null ? c : Class.forName(t.toJavaName(), false, Thread.currentThread().getContextClassLoader());
};
Defensive patterns

Strategy: validation

Validate before calling

if (targetType == Class.class) {
    ResolvedJavaType ct = (ResolvedJavaType) value;
    if (typeToClass.apply(ct) == null) { /* pre-resolve or drop this member before toAnnotation */ }
}

Try / catch

try { toAnnotation(av, Expected.class, fn); } catch (IllegalArgumentException e) { if (e.getMessage().contains("class element type") && e.getMessage().contains("no host class")) { /* widen fn to reach the named class */ } else throw e; }

Prevention

When it happens

Trigger: Calling toAnnotation for an annotation like @ClassList({Foo.class}) where Foo (or a type it references) is not resolvable by the supplied typeToClass — e.g. it belongs to a classloader the lookup cannot reach, or was never recorded in replay metadata.

Common situations: Snapshot/replay of compilations referencing application classes not on the replay classpath; isolated/embedded classloading where annotation members point into the guest namespace; pruned deployment jars missing classes referenced only by annotation members.

Related errors


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