dromara/Sa-Token · error · SaTokenPluginException
SPI 插件加载失败: " + e.getMessage()
Error message
SPI 插件加载失败: " + e.getMessage()
What it means
SaTokenPluginException thrown by SaTokenPluginHolder's SPI loader (outer catch) when loading sa-token plugins from META-INF/services fails for any reason outside the per-file reading block — e.g. failing to locate/open the service resource itself, classloader errors, or exceptions raised while iterating providers. The message embeds the underlying cause's message ('SPI 插件加载失败: ' + e.getMessage()) and the original exception is chained, so the real reason is in getCause().
Source
Thrown at sa-token-core/src/main/java/cn/dev33/satoken/plugin/SaTokenPluginHolder.java:111
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> resources = classLoader.getResources(path);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
try (InputStream is = url.openStream()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
// 忽略空行和注释行
if (!line.isEmpty() && !line.startsWith("#")) {
Class<?> clazz = Class.forName(line, true, classLoader);
T instance = serviceInterface.cast(clazz.getDeclaredConstructor().newInstance());
providers.add(instance);
}
}
} catch (Exception e) {
throw new SaTokenPluginException("SPI 插件加载失败: " + e.getMessage(), e);
}
}
} catch (Exception e) {
throw new SaTokenPluginException("SPI 插件加载失败: " + e.getMessage(), e);
}
return providers;
}
// ------------------- 插件管理 -------------------
/**
* 所有插件的集合
*/
private final List<SaTokenPlugin> pluginList = new ArrayList<>();
/**View on GitHub (pinned to ac2c7f6e94)
Solutions
- Inspect the chained cause: catch SaTokenPluginException and read getCause() to find the real failure (ClassNotFound, IOException, etc.)
- Verify the sa-token integration jars' META-INF/services files survive packaging (enable ServicesResourceTransformer in maven-shade-plugin)
- Align all sa-token modules to one version and remove duplicates from the dependency tree (mvn dependency:tree)
Example fix
// before: shade plugin merges jars without merging services
// startup -> SaTokenPluginException: SPI 插件加载失败: ...
// after (pom.xml)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</plugin> Defensive patterns
Strategy: try-catch
Validate before calling
// before relying on SPI plugins, verify the service resources are visible:
Enumeration<URL> urls = getClass().getClassLoader().getResources("META-INF/services/cn.dev33.satoken.plugin.SaTokenPlugin");
if (!urls.hasMoreElements()) { /* no plugins will load; check packaging */ } Try / catch
try {
// trigger plugin loading
} catch (SaTokenPluginException e) {
Throwable cause = e.getCause();
// classify: ClassNotFound -> version/classpath; IOException -> packaging; log cause for diagnosis
throw e;
} Prevention
- Keep all sa-token modules at one version and prune duplicates from the dependency tree
- Configure shade/assembly plugins to merge META-INF/services entries
- Run the app once in CI with verbose classloading to catch SPI breakage early
When it happens
Trigger: SaTokenPluginHolder's service-loading routine runs at startup; any exception other than the inner line-parsing/instantiation block (e.g. getResources() failure, stream/IO errors at the outer level) lands in this outer catch and is rethrown as 'SPI 插件加载失败: ...'.
Common situations: Broken fat-jar/shaded jar that mangles META-INF/services entries; classloader restrictions in app servers (Tomcat shared libs, OSGi) preventing resource access; a service file naming a class whose static initializer throws; conflicting sa-token plugin versions on the classpath.
Related errors
- 插件不可为空
- 插件 [ " + plugin.getClass().getCanonicalName() + " ] 已安装,不可重复
- 插件 [
- 10002
- 注解参数配置错误,格式应如:username:password
AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14).
Data as JSON: /api/errors/50b0b61158d3251c.
Report an issue: GitHub.