geektutu/7days-golang · error

rpc: service already defined:

Error message

rpc: service already defined: 

What it means

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.

Source

Thrown at gee-rpc/day4-timeout/server.go:222

		}
		go server.ServeConn(conn)
	}
}

// Accept accepts connections on the listener and serves requests
// for each incoming connection.
func Accept(lis net.Listener) { DefaultServer.Accept(lis) }

// Register publishes in the server the set of methods of the
// receiver value that satisfy the following conditions:
//	- exported method of exported type
//	- two arguments, both of exported type
//	- the second argument is a pointer
//	- one return value, of type error
func (server *Server) Register(rcvr interface{}) error {
	s := newService(rcvr)
	if _, dup := server.serviceMap.LoadOrStore(s.name, s); dup {
		return errors.New("rpc: service already defined: " + s.name)
	}
	return nil
}

// Register publishes the receiver's methods in the DefaultServer.
func Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }

View on GitHub (pinned to cf36443821)

Solutions

  1. Register each service only once per Server instance; guard initialization with sync.Once or an idempotency check
  2. Use a separate Server instance if you need independent registration lifecycles (e.g. per test)
  3. If the duplicate is intentional, ignore the returned error or check for it explicitly
  4. Rename one of the colliding receiver types so their reflected service names differ

Example fix

// before
srv.Register(new(Foo))
...
srv.Register(new(Foo)) // panics-free but errors: already defined

// after
var registerOnce sync.Once
registerOnce.Do(func() { _ = srv.Register(new(Foo)) })
Defensive patterns

Strategy: try-catch

Validate before calling

// guard against double registration
if _, loaded := srvServiceNames.LoadOrStore("Foo", true); loaded {
	// skip duplicate Register call
} else {
	_ = srv.Register(new(Foo))
}

Try / catch

if err := srv.Register(new(Foo)); err != nil {
	if strings.Contains(err.Error(), "rpc: service already defined") {
		log.Println("Foo already registered; ignoring")
	} else {
		return err
	}
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03). Data as JSON: /api/errors/502c8c0dbb63a76f. Report an issue: GitHub.