{"record":{"id":"91028a2849453272","repo":"openimsdk/open-im-server","slug":"serve-end","errorCode":null,"errorMessage":"serve end","messagePattern":"serve end","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/common/startrpc/start.go","lineNumber":253,"sourceCode":"\t\trpcGracefulStop = make(chan struct{})\n\t\trpcPort := rpcListener.Addr().(*net.TCPAddr).Port\n\t\tlog.ZDebug(ctx, \"rpc start register\", \"rpcRegisterName\", rpcRegisterName, \"registerIP\", registerIP, \"rpcPort\", rpcPort)\n\t\tgrpcOpt := grpc.WithTransportCredentials(insecure.NewCredentials())\n\t\trpcGracefulStop = make(chan struct{})\n\t\tgo func() {\n\t\t\t<-ctx.Done()\n\t\t\trpcServer.GracefulStop()\n\t\t\tclose(rpcGracefulStop)\n\t\t}()\n\t\tif err := client.Register(ctx, rpcRegisterName, registerIP, rpcListener.Addr().(*net.TCPAddr).Port, grpcOpt); err != nil {\n\t\t\tcancel(fmt.Errorf(\"rpc register %s %w\", rpcRegisterName, err))\n\t\t\treturn\n\t\t}\n\n\t\tgo func() {\n\t\t\terr := rpcServer.Serve(rpcListener)\n\t\t\tif err == nil {\n\t\t\t\terr = fmt.Errorf(\"serve end\")\n\t\t\t}\n\t\t\tcancel(fmt.Errorf(\"rpc %s %w\", rpcRegisterName, err))\n\t\t}()\n\t}\n\n\terr = rpcFn(ctx, config, client, &grpcServiceRegistrar{onRegisterService: onGrpcServiceRegistrar})\n\tif err != nil {\n\t\treturn err\n\t}\n\t<-ctx.Done()\n\tlog.ZDebug(ctx, \"cmd wait done\", \"err\", context.Cause(ctx))\n\tif rpcGracefulStop != nil {\n\t\ttimeout := time.NewTimer(time.Second * 15)\n\t\tdefer timeout.Stop()\n\t\tselect {\n\t\tcase <-timeout.C:\n\t\t\tlog.ZWarn(ctx, \"rcp graceful stop timeout\", nil)\n\t\tcase <-rpcGracefulStop:","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/openimsdk/open-im-server/blob/175a7bb0673eca18e9d1b10bff4f728da6b1b513/pkg/common/startrpc/start.go#L235-L271","documentation":"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.","triggerScenarios":"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.","commonSituations":"Sibling RPC service in the same Start call failed, cancelling ctx and triggering GracefulStop; listener closed by another goroutine; shutdown racing startup.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := startrpc.Start(ctx, cfg); err != nil {\n    if strings.Contains(err.Error(), \"serve end\") {\n        log.Warn(\"grpc serve returned nil; look for the sibling error that cancelled the context\")\n    }\n    return err\n}","preventionTips":["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"],"tags":["grpc","lifecycle","shutdown"],"backgroundTag":"grpc-server-stopped-unexpectedly","analyzedSha":"175a7bb0673eca18e9d1b10bff4f728da6b1b513","analyzedAt":"2026-09-04T16:52:56.821Z","contentChangedAt":"2026-09-04T16:52:56.821Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}