{"record":{"id":"b10b7c6e4cd4f6af","repo":"grpc/grpc-go","slug":"grpc-the-server-has-been-stopped","errorCode":null,"errorMessage":"grpc: the server has been stopped","messagePattern":"grpc: the server has been stopped","errorType":"exception","errorClass":"ErrServerStopped","httpStatus":null,"severity":"error","filePath":"server.go","lineNumber":856,"sourceCode":"\t\tfor m, d := range srv.streams {\n\t\t\tmethods = append(methods, MethodInfo{\n\t\t\t\tName:           m,\n\t\t\t\tIsClientStream: d.ClientStreams,\n\t\t\t\tIsServerStream: d.ServerStreams,\n\t\t\t})\n\t\t}\n\n\t\tret[n] = ServiceInfo{\n\t\t\tMethods:  methods,\n\t\t\tMetadata: srv.mdata,\n\t\t}\n\t}\n\treturn ret\n}\n\n// ErrServerStopped indicates that the operation is now illegal because of\n// the server being stopped.\nvar ErrServerStopped = errors.New(\"grpc: the server has been stopped\")\n\ntype listenSocket struct {\n\tnet.Listener\n\tchannelz *channelz.Socket\n}\n\nfunc (l *listenSocket) Close() error {\n\terr := l.Listener.Close()\n\tchannelz.RemoveEntry(l.channelz.ID)\n\tchannelz.Info(logger, l.channelz, \"ListenSocket deleted\")\n\treturn err\n}\n\n// Serve accepts incoming connections on the listener lis, creating a new\n// ServerTransport and service goroutine for each. The service goroutines\n// read gRPC requests and then call the registered handlers to reply to them.\n// Serve returns when lis.Accept fails with fatal errors.  lis will be closed when\n// this method returns.","sourceCodeStart":838,"sourceCodeEnd":874,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/server.go#L838-L874","documentation":"ErrServerStopped is a package-level sentinel (server.go:856) returned by Server.Serve when the server has already been stopped via Stop or GracefulStop, i.e. s.lis is nil. It signals the operation is now illegal because the server's lifecycle has ended. Serve also closes the passed listener before returning it.","triggerScenarios":"Calling s.Serve(newListener) after s.Stop() or s.GracefulStop() has run; a restart/reload loop that reuses a stopped Server instance instead of constructing a new one.","commonSituations":"Graceful restart logic that keeps the old Server; calling Serve in a goroutine that races with shutdown; integration tests that Stop then Serve again on the same Server.","solutions":["Construct a fresh grpc.NewServer() for each new Serve lifecycle; do not reuse a stopped server.","Guard Serve with your own state flag or only call it once per server instance.","Compare the returned error to grpc.ErrServerStopped and treat it as expected during shutdown rather than a fatal error.","Coordinate shutdown so Serve has fully returned before you attempt any post-stop operations."],"exampleFix":"// before\nsrv := grpc.NewServer()\nsrv.Serve(lis)\nsrv.Stop()\nsrv.Serve(lis2) // returns ErrServerStopped\n\n// after\nsrv := grpc.NewServer()\ngo srv.Serve(lis)\n// on reload:\nsrv.GracefulStop()\nsrv = grpc.NewServer() // new instance\nsrv.Serve(lis2)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := srv.Serve(lis); err != nil {\n    if errors.Is(err, grpc.ErrServerStopped) {\n        // expected during shutdown; ignore\n        return\n    }\n    log.Fatalf(\"Serve failed: %v\", err)\n}","preventionTips":["Create a new grpc.Server for each serve lifecycle.","Track your own started/stopped flag and avoid calling Serve after Stop.","Treat ErrServerStopped as expected in graceful-reload code paths."],"tags":["go","grpc","server","lifecycle"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}