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
- Ensure the ref instance's class implements the exact interfaceClass set on the ServiceConfig.
- For classloader isolation, make sure the interface class is loaded by a shared parent loader so both sides agree on identity.
- 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
- Derive the interface from the ref's implemented interfaces when unsure.
- In multi-loader setups, load the interface via a shared parent classloader.
- Add a wiring test asserting ref implements the declared interface.
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
- Missing method [{}] implement.
- Class {} is not a interface.
- {} is not a interface.
- The interface class <interfaceClass> is not a interface!
- ref not allow null!
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/7d9b55182f202d21.
Report an issue: GitHub.