elastic/elasticsearch · error · IllegalStateException

Failed to inspect class {}. Missing class? {}

Error message

Failed to inspect class {}. Missing class? {}

What it means

Thrown by TestingConventionsCheckTask when reflecting over a candidate test class to decide whether it is a JUnit test. Loading/inspecting the class triggers a NoClassDefFoundError because a type the class references is absent from the classpath the check is using. The catch rethrows as IllegalStateException attaching the class name and the underlying error message.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/TestingConventionsCheckTask.java:237

                        Logging.getLogger(TestingConventionsCheckWorkAction.class)
                            .debug("{} is a test because it has method named '{}'", clazz.getName(), method.getName());
                        return true;
                    }
                    if (isAnnotated(method, junitAnnotation)) {
                        Logging.getLogger(TestingConventionsCheckWorkAction.class)
                            .debug(
                                "{} is a test because it has method '{}' annotated with '{}'",
                                clazz.getName(),
                                method.getName(),
                                junitAnnotation.getName()
                            );
                        return true;
                    }
                }
                return false;
            } catch (NoClassDefFoundError e) {
                // Include the message to get more info to get more a more useful message when running Gradle without -s
                throw new IllegalStateException("Failed to inspect class " + clazz.getName() + ". Missing class? " + e.getMessage(), e);
            }
        }

        private static boolean matchesTestMethodNamingConvention(Method method) {
            return method.getName().startsWith(JUNIT3_TEST_METHOD_PREFIX)
                && Modifier.isStatic(method.getModifiers()) == false
                && method.getReturnType().equals(Void.TYPE);
        }

        private static boolean isAnnotated(Method method, Class<?> annotation) {
            return Stream.of(method.getAnnotations())
                .anyMatch(presentAnnotation -> annotation.isAssignableFrom(presentAnnotation.getClass()));
        }

        private static Class<?> loadClassWithoutInitializing(String name, ClassLoader classLoader) {
            try {
                return Class.forName(
                    name,

View on GitHub (pinned to db6a809a66)

Solutions

  1. Read the attached NoClassDefFoundError message to identify the missing type, then add the corresponding testImplementation/testCompileOnly dependency to the failing project.
  2. Run ./gradlew :<project>:dependencies --configuration testCompileClasspath to confirm the missing type's jar is absent.
  3. If the class is genuinely optional, refactor the test to not reference it, or split the test so the offending type lives in a module where the dependency is present.
  4. Re-run :<project>:testingConventions to verify.

Example fix

// before: test references @MyCustomAnnotation from a missing dep
// after: add the dependency in build.gradle
dependencies {
  testImplementation 'org.example:annotations:1.0'
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before the check, ensure all types referenced by test classes are resolvable
// (run a compile + a classpath completeness scan)
./gradlew :<project>:compileTestJava  // must pass cleanly first

Try / catch

try { boolean isTest = inspectTestClass(clazz); }
catch (IllegalStateException e) {
    if (e.getCause() instanceof NoClassDefFoundError) {
        // missing dependency — add it, don't suppress
        throw e;
    }
    throw e;
}

Prevention

When it happens

Trigger: The convention check loads classes from compiled test output using a classloader, and calls isJUnit3OrLaterTestMethod / annotation inspection which requires resolving referenced types. If a test class references a type not on the configured test classpath (e.g. a missing transitive dependency, a class only present at runtime), the JVM raises NoClassDefFoundError during reflection.

Common situations: A test class references an annotation or super type from a dependency not declared as a testCompile/testImplementation; running the convention check in isolation without the full test runtime classpath; a recently removed dependency still referenced by legacy test code; shaded/renamed classes after a dependency upgrade.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/b6a7545e12e50171. Report an issue: GitHub.