oracle/graal · error · IllegalArgumentException
Not an annotation type
Error message
Not an annotation type
What it means
After locating the include folder, findJNIHeaders() searches it (depth 2) for each required header name in INCLUDES (jni.h, jni_md.h and friends). If a header cannot be found it throws IllegalStateException. Note the message prints res[i] (the still-null/empty slot) instead of the missing name, so read the source INCLUDES array to know which file is actually missing.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/annotation/AnnotationValueType.java:70
* @interface Named { String value(); }
*
* @interface Anno { Named named() default @Named("foo"); }
*
* Creating the AnnotationValueType for Anno will recursively call getInstance to create the
* AnnotationValueType for Named.
*/
AnnotationValueType value = ANNOTATION_TYPES.get(annotationClass);
if (value != null) {
return value;
}
AnnotationValueType created = new AnnotationValueType(annotationClass);
AnnotationValueType existing = ANNOTATION_TYPES.putIfAbsent(annotationClass, created);
return existing != null ? existing : created;
}
private AnnotationValueType(ResolvedJavaType annotationClass) {
if (!annotationClass.isAnnotation()) {
throw new IllegalArgumentException("Not an annotation type");
}
ResolvedJavaMethod[] methods = annotationClass.getDeclaredMethods();
memberTypes = new EconomicHashMap<>(methods.length + 1);
memberDefaults = new EconomicHashMap<>(0);
for (ResolvedJavaMethod method : methods) {
if (method.isPublic() &&
method.isAbstract() &&
!method.isSynthetic()) {
if (method.getSignature().getParameterCount(false) != 0) {
throw new IllegalArgumentException(method + " has params");
}
String name = method.getName();
ResolvedJavaType memberType = method.getSignature().getReturnType(annotationClass).resolve(annotationClass);
memberTypes.put(name, memberType);
View on GitHub (pinned to a66e9ccd1d)
Solutions
- Check that $JAVA_HOME/include contains jni.h and a platform subfolder (linux/darwin/win32) with jni_md.h; reinstall the JDK-devel package if not.
- Point java.home at a complete, official JDK distribution.
- If the message is ambiguous (prints null), cross-check the INCLUDES array in JNI.java to identify the missing file.
Defensive patterns
Strategy: validation
Validate before calling
Path inc = Paths.get(System.getProperty("java.home"), "include");
for (String h : new String[]{"jni.h", "linux/jni_md.h"}) { // adjust platform dir for darwin/win32
if (!Files.exists(inc.resolve(h))) {
throw new IllegalStateException("Missing JNI header " + h + " under " + inc);
}
} Prevention
- Smoke-test that $JAVA_HOME/include contains jni.h plus the platform subfolder with jni_md.h.
- Prefer official JDK distributions over distro-split or hand-copied JDK folders.
When it happens
Trigger: A JDK whose include/ exists but is missing platform headers (jni_md.h lives in include/linux or include/darwin and was not packaged); a partially installed or corrupted JDK; a nonstandard JDK layout where headers sit deeper than depth 2 from include/.
Common situations: Distro JDK packages that split headers across packages; hand-copied JDK directories that missed include/<platform>/ subfolders; stripped container images.
Related errors
- Could not execute {jdk.java}
- nargs not allowed
- illegal type for element %s: %s
- %s missing element %s
- Set the JVMCI_VERSION_CHECK environment variable to "ignore"
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/2bd830fbe7f08ad8.
Report an issue: GitHub.