apache/dubbo · error · IllegalStateException

The interface class <interfaceClass> is not a interface!

Error message

The interface class <interfaceClass> is not a interface!

What it means

Thrown by ServiceConfigBase.checkInterface when the interfaceClass is not an interface AND none of the configured protocols permit a non-interface class. A non-interface class is only allowed for the Triple protocol (with noInterfaceSupport=true) or the REST protocol; otherwise Dubbo requires a true interface.

Source

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

    @Override
    public void checkInterface() {
        if (interfaceClass == null || interfaceClass.isInterface()) {
            return;
        }
        List<ProtocolConfig> protocols = getProtocols();
        if (CollectionUtils.isEmpty(protocols)) {
            return;
        }
        for (ProtocolConfig protocol : protocols) {
            String name = protocol.getName();
            if (CommonConstants.TRIPLE.equals(name) && Boolean.TRUE.equals(protocol.isNoInterfaceSupport())) {
                return;
            }
            if (Constants.REST_PROTOCOL.equals(name)) {
                return;
            }
        }
        throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
    }

    @Transient
    public T getRef() {
        return ref;
    }

    public void setRef(T ref) {
        this.ref = ref;
    }

    @Parameter(excluded = true)
    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Expose an actual Java interface as the service type instead of a concrete/abstract class.
  2. If using Triple and you must expose a concrete class, set protocol.noInterfaceSupport=true.
  3. Switch to the REST protocol if a non-interface service class is required.

Example fix

// before
ProtocolConfig p = new ProtocolConfig("tri");
p.setNoInterfaceSupport(false);
serviceConfig.setInterface(FooServiceImpl.class); // concrete

// after
p.setNoInterfaceSupport(true); // or expose FooService interface instead
Defensive patterns

Strategy: validation

Validate before calling

// Before export, confirm either it is an interface or a permitted protocol
Class<?> iface = serviceConfig.getInterfaceClass();
boolean nonInterfaceAllowed = serviceConfig.getProtocols().stream().anyMatch(p ->
    (CommonConstants.TRIPLE.equals(p.getName()) && Boolean.TRUE.equals(p.isNoInterfaceSupport()))
    || Constants.REST_PROTOCOL.equals(p.getName()));
if (iface != null && !iface.isInterface() && !nonInterfaceAllowed) {
    throw new IllegalStateException(iface + " is not an interface and no protocol permits non-interface classes");
}
serviceConfig.export();

Type guard

static boolean protocolAllowsNonInterface(List<ProtocolConfig> protocols) {
    return protocols.stream().anyMatch(p ->
        (CommonConstants.TRIPLE.equals(p.getName()) && Boolean.TRUE.equals(p.isNoInterfaceSupport()))
        || Constants.REST_PROTOCOL.equals(p.getName()));
}

Try / catch

try {
    serviceConfig.checkInterface();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("is not a interface")) {
        // switch interfaceClass to an interface, or enable tri noInterfaceSupport / REST
    }
    throw e;
}

Prevention

When it happens

Trigger: checkInterface() runs (e.g. during setInterface or refresh) with a non-interface interfaceClass, protocols set, and every protocol is neither (Triple + noInterfaceSupport==true) nor REST.

Common situations: Exporting a concrete/abstract class as a service on the default dubbo protocol (which requires an interface). Setting noInterfaceSupport=false (default) on a Triple service that exposes a concrete class. Mixing a non-interface impl with a protocol that does not support it.

Related errors


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