{"record":{"id":"172d78c33d100bfe","repo":"spring-projects/spring-ai","slug":"classnotfoundexception-wrapped-runtimeexception","errorCode":null,"errorMessage":"ClassNotFoundException (wrapped RuntimeException)","messagePattern":"ClassNotFoundException \\(wrapped RuntimeException\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-model/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java","lineNumber":65,"sourceCode":"\n\tprivate static final Log log = LogFactory.getLog(AiRuntimeHints.class);\n\n\t/**\n\t * Finds classes in a package that are annotated with JsonInclude or have Jackson\n\t * annotations.\n\t * @param packageName The name of the package to search for annotated classes.\n\t * @return A set of TypeReference objects representing the annotated classes found.\n\t */\n\tpublic static Set<TypeReference> findJsonAnnotatedClassesInPackage(String packageName) {\n\t\tvar annotationTypeFilter = new AnnotationTypeFilter(JsonInclude.class);\n\t\tTypeFilter typeFilter = (metadataReader, metadataReaderFactory) -> {\n\t\t\ttry {\n\t\t\t\tvar clazz = Class.forName(metadataReader.getClassMetadata().getClassName());\n\t\t\t\treturn annotationTypeFilter.match(metadataReader, metadataReaderFactory)\n\t\t\t\t\t\t|| !discoverJacksonAnnotatedTypesFromRootType(clazz).isEmpty();\n\t\t\t}\n\t\t\tcatch (ClassNotFoundException e) {\n\t\t\t\tthrow new RuntimeException(e);\n\t\t\t}\n\t\t};\n\n\t\treturn findClassesInPackage(packageName, typeFilter);\n\t}\n\n\t/**\n\t * Finds classes in a package that are annotated with JsonInclude or have Jackson\n\t * annotations.\n\t * @param packageClass The class in the package to search for annotated classes.\n\t * @return A set of TypeReference objects representing the annotated classes found.\n\t */\n\tpublic static Set<TypeReference> findJsonAnnotatedClassesInPackage(Class<?> packageClass) {\n\t\treturn findJsonAnnotatedClassesInPackage(packageClass.getPackageName());\n\t}\n\n\t/**\n\t * Finds all classes in the specified package that match the given type filter.","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-model/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java#L47-L83","documentation":"AiRuntimeHints.findJsonAnnotatedClassesInPackage scans classpath resources for @JsonSerializable/JSON-annotated classes to register them for native-image reflection; if Class.forName fails to load a discovered class name it wraps ClassNotFoundException in a RuntimeException. This typically indicates inconsistent classpath metadata.","triggerScenarios":"Running native-image hint registration when a class listed in classpath metadata was removed/renamed, shading broke class visibility, or a scanning filter matched a class not present at runtime.","commonSituations":"GraalVM native-image builds after package refactor; fat-jar shading that excludes scanned classes; duplicate/stale class entries from old build artifacts.","solutions":["Run a clean build (mvn clean) to remove stale classpath metadata","Verify the class named in the message still exists and matches the scanned package","Fix shading/relocation config so scanned classes remain loadable in the native image","Update the packageName passed to findJsonAnnotatedClassesInPackage to a package that actually contains the JSON-annotated types"],"exampleFix":"// before\nnew AiRuntimeHints().findJsonAnnotatedClassesInPackage(\"com.example.model\");\n// after (after clean rebuild, narrow to existing package)\nAssert.isTrue(SomeJsonDto.class.getPackageName().startsWith(\"com.example.model\"),\n    \"Scanned package no longer matches relocated classes\");\nnew AiRuntimeHints().findJsonAnnotatedClassesInPackage(\"com.example.model\");","handlingStrategy":"try-catch","validationCode":"// before registering hints, verify the scanned classes resolve\nClass.forName(\"com.example.model.SomeJsonDto\", false, getClass().getClassLoader());","typeGuard":null,"tryCatchPattern":"try {\n    hints.findJsonAnnotatedClassesInPackage(pkg);\n} catch (RuntimeException e) {\n    if (e.getCause() instanceof ClassNotFoundException cnfe) {\n        throw new IllegalStateException(\"Stale classpath metadata for \" + cnfe.getMessage() + \"; run a clean build\");\n    }\n    throw e;\n}","preventionTips":["Run mvn clean after package refactors before native-image builds","Avoid shading/relocation of scanned packages","Keep scanned package names in sync with actual code layout"],"tags":["classpath","reflection","graalvm","native-image","spring-ai"],"backgroundTag":"class-not-found","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}