{"record":{"id":"ddcb3885feb2a061","repo":"AdguardTeam/AdGuardHome","slug":"shutting-down-web-w","errorCode":null,"errorMessage":"shutting down web: %w","messagePattern":"shutting down web: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/next/cmd/service.go","lineNumber":111,"sourceCode":"\tif err != nil {\n\t\ts.logger.ErrorContext(ctx, \"writing pidfile\", slogutil.KeyError, err)\n\n\t\treturn\n\t}\n\n\ts.logger.DebugContext(ctx, \"wrote pid\", \"file\", s.pidFilePath, \"pid\", pid)\n}\n\n// Shutdown implements the [service.Interface] interface for *serviceMgr.\nfunc (s *serviceMgr) Shutdown(ctx context.Context) (err error) {\n\ts.confMgrMu.RLock()\n\tdefer s.confMgrMu.RUnlock()\n\n\tvar errs []error\n\n\terr = s.confMgr.Web().Shutdown(ctx)\n\tif err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"shutting down web: %w\", err))\n\t}\n\n\terr = s.confMgr.DNS().Shutdown(ctx)\n\tif err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"shutting down dnssvc: %w\", err))\n\t}\n\n\ts.removePID(ctx)\n\n\treturn errors.Join(errs...)\n}\n\n// removePID removes the PID file.  Any errors are reported to log.\nfunc (s *serviceMgr) removePID(ctx context.Context) {\n\tif s.pidFilePath == \"\" {\n\t\treturn\n\t}\n","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/next/cmd/service.go#L93-L129","documentation":"Graceful shutdown of the web server failed (confMgr.Web().Shutdown); joined with any DNS shutdown error. Usually a timeout waiting for in-flight connections to drain.","triggerScenarios":"Shutdown context expires while HTTP keep-alive connections or long requests (e.g. large queries, slow clients) refuse to close.","commonSituations":"Refresh/reconfigure flow where the shutdown context is too short and clients hold connections open.","solutions":["Increase the shutdown timeout/context deadline","Ensure clients/health-checkers close idle connections","If benign (during restart), verify the process actually exits and the new instance starts"],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 1*time.Second)\n// after\nctx, cancel := context.WithTimeout(ctx, 15*time.Second)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := s.Shutdown(ctx)\nif err != nil {\n\tvar joined interface{ Unwrap() []error }\n\tif errors.As(err, &joined) { /* inspect each; tolerate web drain timeouts */ }\n}","preventionTips":["Give Shutdown a generous context deadline","Close idle keep-alive clients (load balancers, monitors) before shutdown"],"tags":["web","shutdown","timeout"],"backgroundTag":"graceful-shutdown-timeout","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}