{"record":{"id":"502c8c0dbb63a76f","repo":"geektutu/7days-golang","slug":"rpc-service-already-defined-502c8c","errorCode":null,"errorMessage":"rpc: service already defined: ","messagePattern":"rpc: service already defined: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day4-timeout/server.go","lineNumber":222,"sourceCode":"\t\t}\n\t\tgo server.ServeConn(conn)\n\t}\n}\n\n// Accept accepts connections on the listener and serves requests\n// for each incoming connection.\nfunc Accept(lis net.Listener) { DefaultServer.Accept(lis) }\n\n// Register publishes in the server the set of methods of the\n// receiver value that satisfy the following conditions:\n//\t- exported method of exported type\n//\t- two arguments, both of exported type\n//\t- the second argument is a pointer\n//\t- one return value, of type error\nfunc (server *Server) Register(rcvr interface{}) error {\n\ts := newService(rcvr)\n\tif _, dup := server.serviceMap.LoadOrStore(s.name, s); dup {\n\t\treturn errors.New(\"rpc: service already defined: \" + s.name)\n\t}\n\treturn nil\n}\n\n// Register publishes the receiver's methods in the DefaultServer.\nfunc Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }\n","sourceCodeStart":204,"sourceCodeEnd":229,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day4-timeout/server.go#L204-L229","documentation":"Register publishes a receiver's methods in the server's serviceMap keyed by the service name derived from the receiver type. If a service with the same name is already registered, LoadOrStore reports a duplicate and Register returns this error rather than silently overwriting the existing registration.","triggerScenarios":"Calling server.Register(new(Foo)) twice on the same Server, or registering two different types whose reflected service name collides (e.g. same type name in different packages).","commonSituations":"Initialization code that may run twice on restart/reload; registering the same service on both DefaultServer and a custom server by mistake; test suites re-registering services across test cases without a fresh Server.","solutions":["Register each service only once per Server instance; guard initialization with sync.Once or an idempotency check","Use a separate Server instance if you need independent registration lifecycles (e.g. per test)","If the duplicate is intentional, ignore the returned error or check for it explicitly","Rename one of the colliding receiver types so their reflected service names differ"],"exampleFix":"// before\nsrv.Register(new(Foo))\n...\nsrv.Register(new(Foo)) // panics-free but errors: already defined\n\n// after\nvar registerOnce sync.Once\nregisterOnce.Do(func() { _ = srv.Register(new(Foo)) })","handlingStrategy":"try-catch","validationCode":"// guard against double registration\nif _, loaded := srvServiceNames.LoadOrStore(\"Foo\", true); loaded {\n\t// skip duplicate Register call\n} else {\n\t_ = srv.Register(new(Foo))\n}","typeGuard":null,"tryCatchPattern":"if err := srv.Register(new(Foo)); err != nil {\n\tif strings.Contains(err.Error(), \"rpc: service already defined\") {\n\t\tlog.Println(\"Foo already registered; ignoring\")\n\t} else {\n\t\treturn err\n\t}\n}","preventionTips":["Register services exactly once, e.g. inside sync.Once or main init only","Do not re-run registration logic on config reload without recreating the Server","Use unique receiver type names to avoid reflected-name collisions","Treat duplicate-registration errors as bugs and alert on them in tests"],"tags":["rpc","server","registration","duplicate","go"],"backgroundTag":"service-already-registered","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}