apache/dubbo · error · IllegalStateException

The class <getClassDesc(ref.getClass())> unimplemented inter

Error message

The class <getClassDesc(ref.getClass())> unimplemented interface <getClassDesc(interfaceClass)>!

What it means

Thrown by ServiceConfigBase.checkRef when the ref instance is not assignable to the declared interfaceClass. The implementation must be an instance of the interface the service exposes, otherwise the export is rejected.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java:154

    }

    public boolean shouldDelay() {
        Integer delay = getDelay();
        return delay != null && delay > 0;
    }

    @Override
    public Integer getDelay() {
        return (delay == null && provider != null) ? provider.getDelay() : delay;
    }

    protected void checkRef() {
        // reference should not be null, and is the implementation of the given interface
        if (ref == null) {
            throw new IllegalStateException("ref not allow null!");
        }
        if (!interfaceClass.isInstance(ref)) {
            throw new IllegalStateException("The class "
                    + getClassDesc(ref.getClass()) + " unimplemented interface "
                    + getClassDesc(interfaceClass) + "!");
        }
    }

    private String getClassDesc(Class clazz) {
        ClassLoader classLoader = clazz.getClassLoader();
        return clazz.getName() + "[classloader=" + classLoader.getClass().getName() + "@" + classLoader.hashCode()
                + "]";
    }

    public Optional<String> getContextPath(ProtocolConfig protocolConfig) {
        String contextPath = protocolConfig.getContextpath();
        if (StringUtils.isEmpty(contextPath) && provider != null) {
            contextPath = provider.getContextpath();
        }
        return Optional.ofNullable(contextPath);
    }

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Ensure the ref instance's class implements the exact interfaceClass set on the ServiceConfig.
  2. For classloader isolation, make sure the interface class is loaded by a shared parent loader so both sides agree on identity.
  3. Re-derive interfaceClass from the ref if appropriate, or align setInterface with the impl.

Example fix

// before
serviceConfig.setInterface(BarService.class);
serviceConfig.setRef(new FooServiceImpl()); // does not implement BarService

// after
serviceConfig.setInterface(FooService.class);
serviceConfig.setRef(new FooServiceImpl());
Defensive patterns

Strategy: type-guard

Validate before calling

// Verify assignability before export
Class<?> iface = serviceConfig.getInterfaceClass();
if (!iface.isInstance(serviceConfig.getRef())) {
    throw new IllegalStateException(serviceConfig.getRef().getClass()
        + " does not implement " + iface);
}
serviceConfig.export();

Type guard

static boolean refImplementsInterface(Object ref, Class<?> iface) {
    return ref != null && iface != null && iface.isInstance(ref);
}

Try / catch

try {
    serviceConfig.export();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("unimplemented interface")) {
        // align the interface type with the actual ref implementation
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling checkRef()/export() where ref != null but interfaceClass.isInstance(ref) is false — i.e. the impl class does not implement the declared interface.

Common situations: Setting an interface that the implementation does not implement (mismatch between setInterface and setRef). Classloader isolation where the same interface name resolves to different class objects in different loaders. Copy-paste error wiring the wrong impl to a service. Generics erasure causing the runtime check to fail.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/7d9b55182f202d21. Report an issue: GitHub.