{"record":{"id":"1a5399fdf0726461","repo":"apache/shenyu","slug":"load-extension-resources-error","errorCode":null,"errorMessage":"load extension resources error","messagePattern":"load extension resources error","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"shenyu-spi/src/main/java/org/apache/shenyu/spi/ExtensionLoader.java","lineNumber":295,"sourceCode":"                }\n            }\n        } catch (IOException t) {\n            LOG.error(\"load extension class error {}\", fileName, t);\n        }\n    }\n    \n    private void loadResources(final Map<String, ClassEntity> classes, final URL url) throws IOException {\n        try (InputStream inputStream = url.openStream()) {\n            Properties properties = new Properties();\n            properties.load(inputStream);\n            properties.forEach((k, v) -> {\n                String name = (String) k;\n                String classPath = (String) v;\n                if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(classPath)) {\n                    try {\n                        loadClass(classes, name, classPath);\n                    } catch (ClassNotFoundException e) {\n                        throw new IllegalStateException(\"load extension resources error\", e);\n                    }\n                }\n            });\n        } catch (IOException e) {\n            throw new IllegalStateException(\"load extension resources error\", e);\n        }\n    }\n    \n    private void loadClass(final Map<String, ClassEntity> classes,\n                           final String name, final String classPath) throws ClassNotFoundException {\n        Class<?> subClass = Objects.nonNull(this.classLoader) ? Class.forName(classPath, true, this.classLoader) : Class.forName(classPath);\n        if (!clazz.isAssignableFrom(subClass)) {\n            throw new IllegalStateException(\"load extension resources error,\" + subClass + \" subtype is not of \" + clazz);\n        }\n        if (!subClass.isAnnotationPresent(Join.class)) {\n            throw new IllegalStateException(\"load extension resources error,\" + subClass + \" without @\" + Join.class + \" annotation\");\n        }\n        ClassEntity oldClassEntity = classes.get(name);","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-spi/src/main/java/org/apache/shenyu/spi/ExtensionLoader.java#L277-L313","documentation":"loadResources reads the interface's META-INF/shenyu/ resource URLs, parses name->classPath entries, and loads each class. This IllegalStateException wraps a ClassNotFoundException: an entry in the SPI resource file names a class that the classloader cannot find.","triggerScenarios":"A META-INF/shenyu/<interface> file contains a classPath (fully-qualified name) whose class is not on the classpath when any extension of that interface is first loaded.","commonSituations":"Optional implementation jar not included in the deployment; class moved/renamed in a version upgrade while the old resource file entry remains; fat-jar packaging omitted a module; typos in the FQCN.","solutions":["Add the jar/module containing the listed class to the classpath","Correct the classPath entry in META-INF/shenyu/<interface-fqcn>","Remove stale entries for classes that no longer exist after an upgrade","Verify packaging (e.g. shenyu-dist/Makefile) includes the extension module"],"exampleFix":"// before (META-INF/shenyu/org.apache.shenyu.loadbalance.LoadBalance)\nroundRobin=org.apache.shenyu.loadbalance.RoundRobinLoadBalance\n// after — class moved packages, update the entry\nroundRobin=org.apache.shenyu.spi.loadbalance.RoundRobinLoadBalance","handlingStrategy":"try-catch","validationCode":"// pre-check that the class named in the resource is loadable\nClass.forName(\"org.apache.shenyu.loadbalance.RoundRobinLoadBalance\", true, classLoader);","typeGuard":null,"tryCatchPattern":"try { T ext = loader.getJoin(name); } catch (IllegalStateException e) { Throwable cause = e.getCause(); log.error(\"SPI resource load failed, cause: {}\", cause, cause); throw e; }","preventionTips":["Declare optional extension modules explicitly in your build/assembly","After upgrades, regenerate META-INF/shenyu/ files for moved classes","Run an init-time load of all extensions to fail fast"],"tags":["spi","classpath","class-not-found"],"backgroundTag":"class-not-found","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}