alibaba/canal · error · IllegalStateException

Extension instance(name: {}, class: {}) could not be instan

Error message

Extension instance(name: {}, class: {})  could not be instantiated: {}

What it means

Thrown by createExtension(name, spiDir, standbyDir) when clazz.newInstance() (or the ConcurrentHashMap put) throws — e.g. the implementation class has no public no-arg constructor, is abstract, or its constructor threw an exception. The throwable's message is appended. This indicates the extension class was found but could not be instantiated.

Source

Thrown at connector/core/src/main/java/com/alibaba/otter/canal/connector/core/spi/ExtensionLoader.java:180

        return getExtension(cachedDefaultName, spiDir, standbyDir);
    }

    @SuppressWarnings("unchecked")
    public T createExtension(String name, String spiDir, String standbyDir) {
        Class<?> clazz = getExtensionClasses(spiDir, standbyDir).get(name);
        if (clazz == null) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
                                            + ")  could not be instantiated: class could not be found");
        }
        try {
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
                                            + ")  could not be instantiated: " + t.getMessage(), t);
        }
    }

    @SuppressWarnings("unchecked")
    private T createExtension(String name, String key, String spiDir, String standbyDir) {
        Class<?> clazz = getExtensionClasses(spiDir, standbyDir).get(name);
        if (clazz == null) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
                                            + ")  could not be instantiated: class could not be found");
        }
        try {
            T instance = (T) EXTENSION_KEY_INSTANCE.get(name + "-" + key);
            if (instance == null) {
                EXTENSION_KEY_INSTANCE.putIfAbsent(name + "-" + key, clazz.newInstance());
                instance = (T) EXTENSION_KEY_INSTANCE.get(name + "-" + key);
            }
            return instance;

View on GitHub (pinned to 87be50e876)

Solutions

  1. Ensure the implementation has a public no-arg constructor.
  2. Move constructor side-effects (connection, config reads) into an init/start lifecycle method rather than the constructor.
  3. Inspect the wrapped cause (t.getMessage()/getCause()) for the real instantiation failure and fix that.
  4. If using a custom jar, confirm it is not obfuscated in a way that hides the constructor.

Example fix

// before
public class MyProducer implements CanalMQProducer {
    public MyProducer(Config cfg) { ... }   // no no-arg ctor
}
// after
public class MyProducer implements CanalMQProducer {
    public MyProducer() { }                 // SPI instantiates this
    public void init(Config cfg) { ... }    // called after
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the implementation has a public no-arg ctor before requesting
Class<?> impl = resolveImplClass(interfaceType, name);
if (impl != null) {
    try { impl.getConstructor(); }
    catch (NoSuchMethodException nsme) {
        throw new IllegalStateException(impl + " needs a public no-arg constructor");
    }
}

Type guard

boolean isInstantiableSpi(Class<?> impl) {
    try {
        return impl != null && !Modifier.isAbstract(impl.getModifiers())
            && impl.getConstructor() != null;
    } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
    return loader.getExtension(name, spiDir, standbyDir);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("could not be instantiated")) {
        Throwable c = e.getCause();
        // inspect c: add no-arg ctor or move init out of constructor
    }
    throw e;
}

Prevention

When it happens

Trigger: The SPI implementation class lacks an accessible public no-arg constructor; the constructor threw (NPE on a required field, failed inner resource init, security manager denial); the class is abstract or an array/primitive.

Common situations: Custom extension whose constructor depends on config not yet available; constructor performs network/resource init that fails; class was shaded/obfuscated removing the public constructor; Java 9+ module access restrictions.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/971854c73c6c3a72. Report an issue: GitHub.