alibaba/canal · error · RuntimeException
load extension jar failed!
Error message
load extension jar failed!
What it means
Thrown by loadExtensionClasses when File.toURI().toURL() throws MalformedURLException while iterating plugin jars. This is a defensive guard around converting a discovered jar file into a URL for the per-jar URLClassExtensionLoader/URLClassLoader. In practice toURI().toURL() rarely fails; failure implies a path/URI the JVM cannot turn into a valid URL (encoding oddity, unusual filesystem).
Source
Thrown at connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java:285
// 1. plugin folder,customized extension classLoader
// (jar_dir/plugin)
String dir = File.separator + this.getJarDirectoryPath() + spiDir; // +
// "plugin";
File externalLibDir = new File(dir);
if (!externalLibDir.exists()) {
externalLibDir = new File(File.separator + this.getJarDirectoryPath() + standbyDir);
}
logger.info("extension classpath dir: " + externalLibDir.getAbsolutePath());
if (externalLibDir.exists()) {
File[] files = externalLibDir.listFiles((dir1, name) -> name.endsWith(".jar"));
if (files != null) {
for (File f : files) {
URL url;
try {
url = f.toURI().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException("load extension jar failed!", e);
}
ClassLoader parent = Thread.currentThread().getContextClassLoader();
URLClassLoader localClassLoader;
if (classLoaderPolicy == null || "".equals(classLoaderPolicy)
|| DEFAULT_CLASSLOADER_POLICY.equalsIgnoreCase(classLoaderPolicy)) {
localClassLoader = new URLClassExtensionLoader(new URL[] { url });
} else {
localClassLoader = new URLClassLoader(new URL[] { url }, parent);
}
loadFile(extensionClasses, CANAL_DIRECTORY, localClassLoader);
loadFile(extensionClasses, SERVICES_DIRECTORY, localClassLoader);
}
}
}
}
View on GitHub (pinned to 87be50e876)
Solutions
- Move/rename the offending jar so its absolute path uses plain ASCII alphanumeric/underscore/hyphen characters.
- Ensure the plugin directory is a normal local filesystem path (avoid unusual mounts/symlinks).
- Confirm the jar is a valid zip archive and not a truncated/corrupt file.
Example fix
# before plugin dir contains: /opt/canal/plugin/producer@v2!.jar # after rename to: /opt/canal/plugin/producer-v2.jar
Defensive patterns
Strategy: validation
Validate before calling
// Validate plugin jar paths before the loader scans them
File pluginDir = new File(pluginPath);
File[] jars = pluginDir.listFiles((d, n) -> n.endsWith(".jar"));
if (jars != null) for (File f : jars) {
if (!f.toURI().toString().matches("^[A-Za-z0-9._:/\\-]+$")) {
throw new IllegalStateException("unsafe jar path: " + f);
}
} Try / catch
try {
loader.getExtension(name, spiDir, standbyDir);
} catch (RuntimeException e) {
if (e.getMessage().contains("load extension jar failed")) {
// rename offending jar to plain ASCII and retry
} else throw e;
} Prevention
- Use plain ASCII names for plugin jars and directories.
- Avoid exotic characters/spaces in the canal install path.
When it happens
Trigger: A jar file in the plugin/standby directory whose path yields a malformed URL via toURI().toURL(); exotic filesystem characters that break URI-to-URL conversion.
Common situations: Jar filename or directory path with characters that the URI/URL layer mishandles; symlink or NFS-mounted plugin dir producing an odd file: URI; running on a platform with unusual path encoding.
Related errors
- Extension instance(name: {}, class: {}) could not be instan
- Extension instance(name: ${name}, class: ${type}) could not
- Error when load extension class(interface: ${type}, class li
- Duplicate extension ${type.getName()} name ${n} on ${c.getNa
- alarmHandlerPluginDir [%s] can't find any name endswith ".ja
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/78fff707fd457a07.
Report an issue: GitHub.