geektutu/7days-golang · error

rpc server: can't find service

Error message

rpc server: can't find service 

What it means

The service part of the "Service.Method" request was syntactically valid, but no service with that name is registered in the server's serviceMap. findService fails the Load on serviceMap, meaning the receiver was never published via Register on this server instance.

Source

Thrown at gee-rpc/day6-load-balance/server.go:122

	if err := cc.ReadHeader(&h); err != nil {
		if err != io.EOF && err != io.ErrUnexpectedEOF {
			log.Println("rpc server: read header error:", err)
		}
		return nil, err
	}
	return &h, nil
}

func (server *Server) findService(serviceMethod string) (svc *service, mtype *methodType, err error) {
	dot := strings.LastIndex(serviceMethod, ".")
	if dot < 0 {
		err = errors.New("rpc server: service/method request ill-formed: " + serviceMethod)
		return
	}
	serviceName, methodName := serviceMethod[:dot], serviceMethod[dot+1:]
	svci, ok := server.serviceMap.Load(serviceName)
	if !ok {
		err = errors.New("rpc server: can't find service " + serviceName)
		return
	}
	svc = svci.(*service)
	mtype = svc.method[methodName]
	if mtype == nil {
		err = errors.New("rpc server: can't find method " + methodName)
	}
	return
}

func (server *Server) readRequest(cc codec.Codec) (*request, error) {
	h, err := server.readRequestHeader(cc)
	if err != nil {
		return nil, err
	}
	req := &request{h: h}
	req.svc, req.mtype, err = server.findService(h.ServiceMethod)
	if err != nil {

View on GitHub (pinned to cf36443821)

Solutions

  1. Register the receiver on the server: geeRPC.Register(new(Foo)) before serving.
  2. Verify the registered name matches: GeeRegistry uses the Go type name, so &pkg.Foo{} registers as "Foo".
  3. If using a registry/load balancer, ensure every reachable server instance registers the requested service.

Example fix

// before (server main)
// (nothing registered)
// after
srv := geeRPC.NewServer()
_ = srv.Register(new(Foo))
log.Fatal(srv.Accept(lis))
Defensive patterns

Strategy: validation

Validate before calling

// server side, before Accept
if err := srv.Register(new(Foo)); err != nil { log.Fatalf("register Foo: %v", err) }
// client side, sanity check the name matches the registered Go type
const svc = "Foo" // must equal reflect.TypeOf(Foo{}).Name()

Try / catch

if err := client.Call(ctx, "Foo.Sum", args, reply); err != nil && strings.Contains(err.Error(), "can't find service") { log.Fatalf("service not registered on this server: %v", err) }

Prevention

When it happens

Trigger: Client calls "Foo.Bar" while the server never executed Register(&Foo{}), registered Foo under a different name, or the request reached the wrong server instance (e.g. behind a load balancer where only some instances registered the service).

Common situations: Forgot to call geeRPC.Register in the server main, service struct name differs between packages (Go uses the reflected type name, so an unexported or renamed type registers under a different string), or multiple registry nodes where one has the service and others do not.

Related errors


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