apache/dubbo · error · RpcException

Local service for {getUrl().getServiceInterface()} has not b

Error message

Local service for {getUrl().getServiceInterface()} has not been exposed yet!

What it means

Thrown by ScopeClusterInvoker.isInjvmExported when the call is forced to be local (scope=local, or the injvm protocol flag set / RpcContext local-invoke requested) but the service is NOT exported in the current JVM (isExported is false). It refuses to make a remote call because the configuration demanded local scope, yet no local exporter exists.

Source

Thrown at dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/ScopeClusterInvoker.java:272

     */
    private boolean isInjvmExported() {
        Boolean localInvoke = RpcContext.getServiceContext().getLocalInvoke();
        boolean isExportedValue = isExported.get();
        boolean localOnce = (localInvoke != null && localInvoke);
        // Determine whether this call is local
        if (isExportedValue && localOnce) {
            return true;
        }

        // Determine whether this call is remote
        if (localInvoke != null && !localInvoke) {
            return false;
        }

        // When calling locally, determine whether it does not meet the requirements
        if (!isExportedValue && (isForceLocal() || localOnce)) {
            // If it's supposed to be exported to the local JVM ,but it's not, throw an exception
            throw new RpcException(
                    "Local service for " + getUrl().getServiceInterface() + " has not been exposed yet!");
        }

        return isExportedValue && injvmFlag;
    }

    private boolean isForceLocal() {
        return SCOPE_LOCAL.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY))
                || Boolean.TRUE.toString().equalsIgnoreCase(getUrl().getParameter(LOCAL_PROTOCOL));
    }

    /**
     * Creates a new Invoker for the current ScopeClusterInvoker and exports it to the local JVM.
     */
    private void createInjvmInvoker(Exporter<?> exporter) {
        if (injvmInvoker == null) {
            synchronized (createLock) {
                if (injvmInvoker == null) {

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Expose the service locally in the same JVM (ensure the provider is configured and started, e.g. scope=local export) so an injvm exporter exists before the call.
  2. Remove the local-scope forcing (scope=local / injvm flag / setLocalInvoke(true)) to allow a normal remote invocation.
  3. Fix provider startup ordering so the injvm exporter is registered before the consumer issues a local-scoped call.
  4. Verify the service interface name in the message matches a service this JVM actually exposes.

Example fix

// before: consumer forces local scope but service not exported in JVM
<dubbo:reference interface="com.acme.Svc" scope="local"/>

// after: allow remote, or also expose locally
<dubbo:reference interface="com.acme.Svc" scope="remote"/>
<!-- plus, if local is desired: -->
<dubbo:service interface="com.acme.Svc" ref="svcImpl" scope="local"/>
Defensive patterns

Strategy: validation

Validate before calling

// Before issuing a local-scoped call, confirm a local exporter exists
if (!isLocalExporterPresent(url.getServiceInterface())) {
    throw new IllegalStateException("service not exported locally; cannot use scope=local");
}

Try / catch

try {
    return service.call(req);
} catch (RpcException e) {
    if (e.getMessage() != null && e.getMessage().endsWith("has not been exposed yet!")) {
        log.error("local scope forced but no injvm exporter; expose locally or use remote", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Url config scope=local (or LOCAL_PROTOCOL/injvm flag true) and the service was never injvm-exported in this JVM; or RpcContext.getServiceContext().setLocalInvoke(true) on a consumer whose provider side has not exposed the service locally; calling a service from a different application/module context that never registered an injvm exporter.

Common situations: Enabling scope=local on a pure consumer application that does not also expose the service in-process; provider failed to start/export so no local exporter was created; cross-module calls where the exporting module loaded later (startup ordering); misreading injvm vs scope semantics and forcing local on a remote-only service.

Related errors


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