jd-opensource/joyagent-jdgenie · error · JdbcBizException
Could not load service provider for Catalog factory.
Error message
Could not load service provider for Catalog factory.
What it means
discoverFactories iterates ServiceLoader.load(JdbcCatalogFactory.class, classLoader); if the SPI machinery itself fails (ServiceConfigurationError — e.g., a provider class listed in META-INF/services cannot be instantiated), it logs and rethrows as JdbcBizException('Could not load service provider for Catalog factory.'). Unlike error 16, providers ARE registered but broken/unloadable.
Solutions
- Inspect the wrapped ServiceConfigurationError cause — it names the failing provider class and reason.
- Fix the META-INF/services entry to match the provider class's actual fully-qualified name.
- Add the missing dependency the provider needs at initialization time.
- Rebuild/redeploy the jar so service files and implementation classes are consistent.
Example fix
// before (META-INF/services/com.jd.genie.data.jdbc.catalog.JdbcCatalogFactory) com.jd.genie.data.jdbc.catalog.MySqlCatalogFactory // class renamed in refactor // after com.jd.genie.data.jdbc.catalog.mysql.MySqlJdbcCatalogFactory
Defensive patterns
Strategy: try-catch
Validate before calling
// verify provider class is loadable before iteration
for (String cls : readServiceProviderLines(cl)) {
try { Class.forName(cls, false, cl); }
catch (Throwable t) { throw new IllegalStateException("Unloadable SPI provider: " + cls, t); }
} Try / catch
try {
JdbcCatalog catalog = JdbcCatalogLoader.load(dialect);
} catch (JdbcBizException e) {
if (e.getMessage().contains("Could not load service provider")) {
// inspect e.getCause() (ServiceConfigurationError) for the broken provider class
} else throw e;
} Prevention
- Keep META-INF/services entries in sync with refactored class names.
- Declare all classes the provider needs at init as hard dependencies.
- Exercise ServiceLoader discovery in a startup health check.
- Beware shading: unmangle/verify provider class names post-relocation.
When it happens
Trigger: A META-INF/services entry names a class that is missing, fails static initialization, or whose constructor throws — ServiceLoader iteration raises ServiceConfigurationError, caught and wrapped by discoverFactories.
Common situations: Partial deployments where the service file exists but the implementation class was relocated/renamed in a refactor; provider class depends on an optional dependency not on the classpath (NoClassDefFoundError during init); shaded jars mangling provider class names.
Related errors
- Could not find any jdbc dialect factories that implement
- Could not find any jdbc dialect factory that can handled
- Multiple jdbc dialect factories can handle
- Failed listing database in catalog
- Failed getting table
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/00af6db234ef6ec1.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/data/jdbc/catalog/JdbcCatalogLoader.java:51
}
if (matchingFactories.size() > 1) {
throw new JdbcBizException("Multiple jdbc dialect factories can handle");
}
return matchingFactories.get(0).createCatalog();
}
private static List<JdbcCatalogFactory> discoverFactories(ClassLoader classLoader) {
try {
final List<JdbcCatalogFactory> result = new LinkedList<>();
ServiceLoader.load(JdbcCatalogFactory.class, classLoader)
.iterator()
.forEachRemaining(result::add);
return result;
} catch (ServiceConfigurationError e) {
log.error("Could not load service provider for Catalog factory.", e);
throw new JdbcBizException(
"Could not load service provider for Catalog factory.", e);
}
}
}
View on GitHub (pinned to 2417e0b8b6)