apache/dubbo · error · IllegalStateException
The local implementation class <localClass.getName()> not im
Error message
The local implementation class <localClass.getName()> not implement interface <interfaceClass.getName()>
What it means
Thrown by AbstractInterfaceConfig.verify during stub/local validation (verifyStubAndLocal): the configured local/stub implementation class does not implement the service interface (interfaceClass.isAssignableFrom(localClass) is false). Dubbo requires the stub/local class to be an implementation of the interface so it can substitute for the real service on the client side.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:485
* side, it is the {@link Class} of the remote service interface
*/
protected void checkStubAndLocal(Class<?> interfaceClass) {
verifyStubAndLocal(local, "Local", interfaceClass);
verifyStubAndLocal(stub, "Stub", interfaceClass);
}
private void verifyStubAndLocal(String className, String label, Class<?> interfaceClass) {
if (ConfigUtils.isNotEmpty(className)) {
Class<?> localClass = ConfigUtils.isDefault(className)
? ReflectUtils.forName(interfaceClass.getName() + label)
: ReflectUtils.forName(className);
verify(interfaceClass, localClass);
}
}
private void verify(Class<?> interfaceClass, Class<?> localClass) {
if (!interfaceClass.isAssignableFrom(localClass)) {
throw new IllegalStateException("The local implementation class " + localClass.getName()
+ " not implement interface " + interfaceClass.getName());
}
try {
// Check if the localClass a constructor with parameter whose type is interfaceClass
ReflectUtils.findConstructor(localClass, interfaceClass);
} catch (NoSuchMethodException e) {
throw new IllegalStateException("No such constructor \"public " + localClass.getSimpleName() + "("
+ interfaceClass.getName() + ")\" in local implementation class " + localClass.getName());
}
}
private void convertRegistryIdsToRegistries() {
computeValidRegistryIds();
if (StringUtils.isEmpty(registryIds)) {
if (CollectionUtils.isEmpty(registries)) {
List<RegistryConfig> registryConfigs = getConfigManager().getDefaultRegistries();
registryConfigs = new ArrayList<>(registryConfigs);View on GitHub (pinned to 3a3043227f)
Solutions
- Make the stub/local class implement the exact service interface (implements com.acme.Greeting).
- If using default naming (local=true), create a class named <InterfaceName>Local that implements the interface.
- Point the stub/local attribute to the correct implementing class.
- Remove the local/stub configuration if no client-side stub is needed.
Example fix
// before
public class GreetingLocal {} // does not implement Greeting
<dubbo:service interface="com.acme.Greeting" local="true"/>
// after
public class GreetingLocal implements Greeting {
public GreetingLocal() {}
// ... implement methods
}
<dubbo:service interface="com.acme.Greeting" local="true"/> Defensive patterns
Strategy: validation
Validate before calling
void assertStubImplements(Class<?> iface, String stubClassName) throws ClassNotFoundException {
Class<?> stub = Class.forName(stubClassName);
if (!iface.isAssignableFrom(stub))
throw new IllegalStateException(stub + " must implement " + iface.getName());
} Type guard
boolean implementsInterface(Class<?> candidate, Class<?> iface) {
return candidate != null && iface.isAssignableFrom(candidate);
} Try / catch
try {
serviceConfig.export(); // or reference
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("The local implementation class") && e.getMessage().contains("not implement interface")) {
// make the stub/local class implement the interface
}
throw e;
} Prevention
- Ensure stub/local classes implement the service interface.
- When using local=true/stub=true, create <Interface>Local/<Interface>Stub implementing the interface.
- Add a compile-time/test check that stubs implement their interface.
When it happens
Trigger: checkStubAndLocal loads the class named by the 'local' or 'stub' attribute (either a custom class or interfaceName+'Local'/'Stub') and checks it implements the interface. If it doesn't, this is thrown. Triggered at export (provider local) or reference (consumer stub) startup.
Common situations: The stub/local class implements a different interface or none. A copy-paste pointed stub to the wrong class. The interface name was changed but the stub class wasn't updated. 'local=true'/'stub=true' (default) made Dubbo look for interfaceName+'Local'/'Stub' which doesn't exist or implements the wrong interface.
Related errors
- No registry config found or it's not a valid config! The reg
- <dubbo:method> name attribute is required! Please check: <du
- Found invalid method config, the interface <interfaceClass.g
- Local service for {getUrl().getServiceInterface()} has not b
- More than 1 default extension name on extension {}: {}
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/2f0c0a03fee28b50.
Report an issue: GitHub.