{"record":{"id":"b6a7545e12e50171","repo":"elastic/elasticsearch","slug":"failed-to-inspect-class-missing-class","errorCode":null,"errorMessage":"Failed to inspect class {}. Missing class? {}","messagePattern":"Failed to inspect class (.+?)\\. Missing class\\? (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/TestingConventionsCheckTask.java","lineNumber":237,"sourceCode":"                        Logging.getLogger(TestingConventionsCheckWorkAction.class)\n                            .debug(\"{} is a test because it has method named '{}'\", clazz.getName(), method.getName());\n                        return true;\n                    }\n                    if (isAnnotated(method, junitAnnotation)) {\n                        Logging.getLogger(TestingConventionsCheckWorkAction.class)\n                            .debug(\n                                \"{} is a test because it has method '{}' annotated with '{}'\",\n                                clazz.getName(),\n                                method.getName(),\n                                junitAnnotation.getName()\n                            );\n                        return true;\n                    }\n                }\n                return false;\n            } catch (NoClassDefFoundError e) {\n                // Include the message to get more info to get more a more useful message when running Gradle without -s\n                throw new IllegalStateException(\"Failed to inspect class \" + clazz.getName() + \". Missing class? \" + e.getMessage(), e);\n            }\n        }\n\n        private static boolean matchesTestMethodNamingConvention(Method method) {\n            return method.getName().startsWith(JUNIT3_TEST_METHOD_PREFIX)\n                && Modifier.isStatic(method.getModifiers()) == false\n                && method.getReturnType().equals(Void.TYPE);\n        }\n\n        private static boolean isAnnotated(Method method, Class<?> annotation) {\n            return Stream.of(method.getAnnotations())\n                .anyMatch(presentAnnotation -> annotation.isAssignableFrom(presentAnnotation.getClass()));\n        }\n\n        private static Class<?> loadClassWithoutInitializing(String name, ClassLoader classLoader) {\n            try {\n                return Class.forName(\n                    name,","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/TestingConventionsCheckTask.java#L219-L255","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the attached NoClassDefFoundError message to identify the missing type, then add the corresponding testImplementation/testCompileOnly dependency to the failing project.","Run ./gradlew :<project>:dependencies --configuration testCompileClasspath to confirm the missing type's jar is absent.","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.","Re-run :<project>:testingConventions to verify."],"exampleFix":"// before: test references @MyCustomAnnotation from a missing dep\n// after: add the dependency in build.gradle\ndependencies {\n  testImplementation 'org.example:annotations:1.0'\n}","handlingStrategy":"try-catch","validationCode":"// Before the check, ensure all types referenced by test classes are resolvable\n// (run a compile + a classpath completeness scan)\n./gradlew :<project>:compileTestJava  // must pass cleanly first","typeGuard":null,"tryCatchPattern":"try { boolean isTest = inspectTestClass(clazz); }\ncatch (IllegalStateException e) {\n    if (e.getCause() instanceof NoClassDefFoundError) {\n        // missing dependency — add it, don't suppress\n        throw e;\n    }\n    throw e;\n}","preventionTips":["Keep testCompileClasspath complete — declare every type a test references.","Run testingConventions locally before pushing so missing classes surface early.","After removing a dependency, grep test sources for dangling references."],"tags":["build","gradle","testing","classpath","classloading"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}