{"record":{"id":"1f9fb3e2efdb4988","repo":"apache/dubbo","slug":"local-service-for-geturl-getserviceinterface","errorCode":null,"errorMessage":"Local service for {getUrl().getServiceInterface()} has not been exposed yet!","messagePattern":"Local service for (.+?) has not been exposed yet!","errorType":"exception","errorClass":"RpcException","httpStatus":null,"severity":"error","filePath":"dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/ScopeClusterInvoker.java","lineNumber":272,"sourceCode":"     */\n    private boolean isInjvmExported() {\n        Boolean localInvoke = RpcContext.getServiceContext().getLocalInvoke();\n        boolean isExportedValue = isExported.get();\n        boolean localOnce = (localInvoke != null && localInvoke);\n        // Determine whether this call is local\n        if (isExportedValue && localOnce) {\n            return true;\n        }\n\n        // Determine whether this call is remote\n        if (localInvoke != null && !localInvoke) {\n            return false;\n        }\n\n        // When calling locally, determine whether it does not meet the requirements\n        if (!isExportedValue && (isForceLocal() || localOnce)) {\n            // If it's supposed to be exported to the local JVM ,but it's not, throw an exception\n            throw new RpcException(\n                    \"Local service for \" + getUrl().getServiceInterface() + \" has not been exposed yet!\");\n        }\n\n        return isExportedValue && injvmFlag;\n    }\n\n    private boolean isForceLocal() {\n        return SCOPE_LOCAL.equalsIgnoreCase(getUrl().getParameter(SCOPE_KEY))\n                || Boolean.TRUE.toString().equalsIgnoreCase(getUrl().getParameter(LOCAL_PROTOCOL));\n    }\n\n    /**\n     * Creates a new Invoker for the current ScopeClusterInvoker and exports it to the local JVM.\n     */\n    private void createInjvmInvoker(Exporter<?> exporter) {\n        if (injvmInvoker == null) {\n            synchronized (createLock) {\n                if (injvmInvoker == null) {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/ScopeClusterInvoker.java#L254-L290","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Remove the local-scope forcing (scope=local / injvm flag / setLocalInvoke(true)) to allow a normal remote invocation.","Fix provider startup ordering so the injvm exporter is registered before the consumer issues a local-scoped call.","Verify the service interface name in the message matches a service this JVM actually exposes."],"exampleFix":"// before: consumer forces local scope but service not exported in JVM\n<dubbo:reference interface=\"com.acme.Svc\" scope=\"local\"/>\n\n// after: allow remote, or also expose locally\n<dubbo:reference interface=\"com.acme.Svc\" scope=\"remote\"/>\n<!-- plus, if local is desired: -->\n<dubbo:service interface=\"com.acme.Svc\" ref=\"svcImpl\" scope=\"local\"/>","handlingStrategy":"validation","validationCode":"// Before issuing a local-scoped call, confirm a local exporter exists\nif (!isLocalExporterPresent(url.getServiceInterface())) {\n    throw new IllegalStateException(\"service not exported locally; cannot use scope=local\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return service.call(req);\n} catch (RpcException e) {\n    if (e.getMessage() != null && e.getMessage().endsWith(\"has not been exposed yet!\")) {\n        log.error(\"local scope forced but no injvm exporter; expose locally or use remote\", e);\n    }\n    throw e;\n}","preventionTips":["Expose the service in-process before forcing scope=local.","Avoid scope=local on pure-consumer applications.","Order provider export before consumer local-scoped calls."],"tags":["cluster","scope","injvm","local","export"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}