grpc/grpc-go · critical · ErrServerStopped
grpc: the server has been stopped
Error message
grpc: the server has been stopped
What it means
Sentinel error ErrServerStopped (server.go:856) returned by Server.Serve (and xds.GRPCServer.Serve at xds/server.go:183) when Serve() is invoked after the server has already been stopped via Stop(), GracefulStop(), or Close(). It signals an illegal lifecycle transition: a gRPC Server is single-use; once stopped its internal listener map (s.lis) is nilled and its quit event has fired, so it cannot accept connections again.
Solutions
- Do not reuse a stopped *grpc.Server; construct a fresh grpc.NewServer() / xds.NewGRPCServer() before calling Serve again.
- Guard Serve with a single-flight/once flag so Stop()/GracefulStop() and Serve cannot race, and so Serve is only called once per server instance.
- If you need live reload, keep the existing Server running and rebuild a new listener+server, swapping them atomically, instead of restarting the same Server.
- Check the returned error with errors.Is(err, grpc.ErrServerStopped) to distinguish this from listener errors and surface a clear lifecycle message.
Example fix
// before srv := grpc.NewServer() srv.Stop() srv.Serve(lis) // returns grpc.ErrServerStopped // after srv := grpc.NewServer() srv.Stop() srv = grpc.NewServer() // build a fresh server register(srv) go srv.Serve(lis)
Defensive patterns
Strategy: validation
Validate before calling
// A grpc.Server is single-use. Validate lifecycle before calling Serve.
if serverStopped {
srv = grpc.NewServer()
registerHandlers(srv)
}
// Then:
if err := srv.Serve(lis); err != nil {
if errors.Is(err, grpc.ErrServerStopped) {
// lifecycle bug: Serve called after Stop/GracefulStop
}
} Try / catch
if err := srv.Serve(lis); err != nil {
if errors.Is(err, grpc.ErrServerStopped) {
// Build a new server instead of reusing the stopped one.
} else {
// ordinary Serve error (listener failure)
}
} Prevention
- Never call Serve twice on the same *grpc.Server; create a fresh server for each restart.
- Use a sync.Once or explicit 'serving' flag to prevent Stop/GracefulStop racing with Serve.
- Treat a stopped server as terminal; rebuild listener + server together on reload.
When it happens
Trigger: Calling server.Serve(lis) a second time, or calling Serve(lis2) on a different listener after Stop()/GracefulStop() returned; in xds, calling GRPCServer.Serve after GRPCServer.Close fired the quit event (checked via s.quit.HasFired() at xds/server.go:182).
Common situations: Restart loops that reuse the same *grpc.Server; HTTP/gRPC muxing where the server is stopped on SIGHUP then Serve is re-entered; tests that defer Stop() then call Serve again; xds.GRPCServer that was Close()d on error being reused.
Related errors
- malformed grpc-timeout
- missing server_listener_resource_name_template in the…
- provider instance is closed
- "allow_rules" is not present
- "allow_rules
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/b10b7c6e4cd4f6af.
Report an issue: GitHub.
Appendix: source
Thrown at server.go:856
for m, d := range srv.streams {
methods = append(methods, MethodInfo{
Name: m,
IsClientStream: d.ClientStreams,
IsServerStream: d.ServerStreams,
})
}
ret[n] = ServiceInfo{
Methods: methods,
Metadata: srv.mdata,
}
}
return ret
}
// ErrServerStopped indicates that the operation is now illegal because of
// the server being stopped.
var ErrServerStopped = errors.New("grpc: the server has been stopped")
type listenSocket struct {
net.Listener
channelz *channelz.Socket
}
func (l *listenSocket) Close() error {
err := l.Listener.Close()
channelz.RemoveEntry(l.channelz.ID)
channelz.Info(logger, l.channelz, "ListenSocket deleted")
return err
}
// Serve accepts incoming connections on the listener lis, creating a new
// ServerTransport and service goroutine for each. The service goroutines
// read gRPC requests and then call the registered handlers to reply to them.
// Serve returns when lis.Accept fails with fatal errors. lis will be closed when
// this method returns.View on GitHub (pinned to 0c51461d27)