openimsdk/open-im-server · error
serve end
Error message
serve end
What it means
The gRPC server's Serve() call returned nil, meaning the server stopped serving without reporting an error (normally only after GracefulStop). Since a running server should never return normally, the code synthesizes a 'serve end' error and cancels the startup context.
Source
Thrown at pkg/common/startrpc/start.go:253
rpcGracefulStop = make(chan struct{})
rpcPort := rpcListener.Addr().(*net.TCPAddr).Port
log.ZDebug(ctx, "rpc start register", "rpcRegisterName", rpcRegisterName, "registerIP", registerIP, "rpcPort", rpcPort)
grpcOpt := grpc.WithTransportCredentials(insecure.NewCredentials())
rpcGracefulStop = make(chan struct{})
go func() {
<-ctx.Done()
rpcServer.GracefulStop()
close(rpcGracefulStop)
}()
if err := client.Register(ctx, rpcRegisterName, registerIP, rpcListener.Addr().(*net.TCPAddr).Port, grpcOpt); err != nil {
cancel(fmt.Errorf("rpc register %s %w", rpcRegisterName, err))
return
}
go func() {
err := rpcServer.Serve(rpcListener)
if err == nil {
err = fmt.Errorf("serve end")
}
cancel(fmt.Errorf("rpc %s %w", rpcRegisterName, err))
}()
}
err = rpcFn(ctx, config, client, &grpcServiceRegistrar{onRegisterService: onGrpcServiceRegistrar})
if err != nil {
return err
}
<-ctx.Done()
log.ZDebug(ctx, "cmd wait done", "err", context.Cause(ctx))
if rpcGracefulStop != nil {
timeout := time.NewTimer(time.Second * 15)
defer timeout.Stop()
select {
case <-timeout.C:
log.ZWarn(ctx, "rcp graceful stop timeout", nil)
case <-rpcGracefulStop:View on GitHub (pinned to 175a7bb067)
Solutions
- Inspect the logs for the sibling error that originally cancelled the context — 'serve end' is secondary
- Ensure nothing closes the rpcListener externally
- Check shutdown/GracefulStop wiring so the server isn't stopped during startup
Defensive patterns
Strategy: try-catch
Try / catch
if err := startrpc.Start(ctx, cfg); err != nil {
if strings.Contains(err.Error(), "serve end") {
log.Warn("grpc serve returned nil; look for the sibling error that cancelled the context")
}
return err
} Prevention
- Treat 'serve end' as secondary — always chase the first logged error
- Never close listeners from other goroutines
- Keep GracefulStop tied to shutdown signals, not startup failures
When it happens
Trigger: rpcServer.Serve(rpcListener) returns nil — the listener was closed or GracefulStop was triggered while startup was still in progress (e.g. another component failed and cancelled ctx), or the listener is closed externally.
Common situations: Sibling RPC service in the same Start call failed, cancelling ctx and triggering GracefulStop; listener closed by another goroutine; shutdown racing startup.
Related errors
- signal %s
- rpc %s %w
- standalone api port is 0
- failed to dial endpoint %s: %v
- failed to initialize connections for service %s: %v
AI-assisted analysis of openimsdk/open-im-server@175a7bb067 (2026-09-04).
Data as JSON: /api/errors/91028a2849453272.
Report an issue: GitHub.