{"record":{"id":"b6c68d3a0d478abf","repo":"grpc/grpc-java","slug":"bound-method-for-fullmethodname-not-same-instan","errorCode":null,"errorMessage":"Bound method for ${fullMethodName} not same instance as method in service descriptor","messagePattern":"Bound method for (.+?) not same instance as method in service descriptor","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/grpc/ServerServiceDefinition.java","lineNumber":141,"sourceCode":"      ServiceDescriptor serviceDescriptor = this.serviceDescriptor;\n      if (serviceDescriptor == null) {\n        List<MethodDescriptor<?, ?>> methodDescriptors\n            = new ArrayList<>(methods.size());\n        for (ServerMethodDefinition<?, ?> serverMethod : methods.values()) {\n          methodDescriptors.add(serverMethod.getMethodDescriptor());\n        }\n        serviceDescriptor = new ServiceDescriptor(serviceName, methodDescriptors);\n      }\n      Map<String, ServerMethodDefinition<?, ?>> tmpMethods = new HashMap<>(methods);\n      for (MethodDescriptor<?, ?> descriptorMethod : serviceDescriptor.getMethods()) {\n        ServerMethodDefinition<?, ?> removed = tmpMethods.remove(\n            descriptorMethod.getFullMethodName());\n        if (removed == null) {\n          throw new IllegalStateException(\n              \"No method bound for descriptor entry \" + descriptorMethod.getFullMethodName());\n        }\n        if (removed.getMethodDescriptor() != descriptorMethod) {\n          throw new IllegalStateException(\n              \"Bound method for \" + descriptorMethod.getFullMethodName()\n                  + \" not same instance as method in service descriptor\");\n        }\n      }\n      if (tmpMethods.size() > 0) {\n        throw new IllegalStateException(\n            \"No entry in descriptor matching bound method \"\n                + tmpMethods.values().iterator().next().getMethodDescriptor().getFullMethodName());\n      }\n      return new ServerServiceDefinition(serviceDescriptor, methods);\n    }\n  }\n}\n","sourceCodeStart":123,"sourceCodeEnd":155,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/api/src/main/java/io/grpc/ServerServiceDefinition.java#L123-L155","documentation":"ServerServiceDefinition.Builder.build() verifies that every method bound via addMethod() refers to the exact same MethodDescriptor instance stored in the service descriptor. If a bound method's descriptor differs by instance (even if logically equal) from the one in the ServiceDescriptor, this IllegalStateException is thrown to protect against internal inconsistency between the builder's bound methods and the service descriptor.","triggerScenarios":"Calling build() on ServerServiceDefinition.Builder after addMethod() was given a MethodDescriptor that is a different object instance than the MethodDescriptor recorded in the ServiceDescriptor for the same full method name — e.g. constructing descriptors independently instead of reusing the same instance.","commonSituations":"Custom server builders that generate MethodDescriptors in two places; code that rebuilds or re-serializes a descriptor; misuse of ServerServiceDefinition.Builder with a ServiceDescriptor created from different descriptor objects; copy-pasted gRPC codegen artifacts.","solutions":["Use the exact same MethodDescriptor instance when calling addMethod() as the one used to build the ServiceDescriptor","Build the ServiceDescriptor from the same bound methods (descriptor methods must be the instances returned by YourServiceGrpc.getFooMethod())","If constructing manually, first build the method list, then derive the ServiceDescriptor from those same MethodDescriptor objects","Log and compare full method names plus object identity (System.identityHashCode) to find which descriptor was duplicated"],"exampleFix":"// before\nMethodDescriptor<Req, Resp> generated = FooGrpc.getBarMethod();\nMethodDescriptor<Req, Resp> custom = generated.toBuilder().build(); // new instance\nbuilder.addMethod(custom); // ServiceDescriptor holds `generated` -> mismatch\n// after\nbuilder.addMethod(FooGrpc.getBarMethod()); // same instance as in the descriptor","handlingStrategy":"validation","validationCode":"if (boundDesc != serviceDescriptor.getMethod(fullMethodName)) {\n  throw new IllegalStateException(\"Descriptor instance mismatch for \" + fullMethodName);\n}","typeGuard":null,"tryCatchPattern":"try {\n  def = builder.build();\n} catch (IllegalStateException e) {\n  throw new ConfigurationException(\"Service definition mismatch: \" + e.getMessage(), e);\n}","preventionTips":["Reuse code-generated MethodDescriptor constants instead of building new ones","Derive the ServiceDescriptor from the same method instances passed to addMethod()","Add an identity assert (assertSame) in tests for each bound method"],"tags":["grpc","rpc","internal-invariant","descriptor"],"backgroundTag":"internal-invariant-violation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}