{"record":{"id":"e7598e4b7833b540","repo":"AdguardTeam/AdGuardHome","slug":"shutdown-failed-w","errorCode":null,"errorMessage":"shutdown failed: %w","messagePattern":"shutdown failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/next/cmd/service.go","lineNumber":149,"sourceCode":"\tif err != nil {\n\t\ts.logger.ErrorContext(ctx, \"removing pidfile\", slogutil.KeyError, err)\n\n\t\treturn\n\t}\n\n\ts.logger.DebugContext(ctx, \"removed pidfile\", \"file\", s.pidFilePath)\n}\n\n// type check\nvar _ service.Refresher = (*serviceMgr)(nil)\n\n// Refresh implements the [service.Refresher] interface for *serviceMgr.\nfunc (s *serviceMgr) Refresh(ctx context.Context) (err error) {\n\ts.logger.InfoContext(ctx, \"reconfiguring started\")\n\n\terr = s.Shutdown(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"shutdown failed: %w\", err)\n\t}\n\n\t// TODO(a.garipov):  This is a very rough way to do it.  Some services can\n\t// be reconfigured without the full shutdown, and the error handling is\n\t// currently not the best.\n\n\tctx, cancel := context.WithTimeout(ctx, defaultTimeoutStart)\n\tdefer cancel()\n\n\terr = s.updConfMgr(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"updating configuration manager: %w\", err)\n\t}\n\n\terr = s.Start(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"restarting services: %w\", err)\n\t}","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/next/cmd/service.go#L131-L167","documentation":"Refresh performs a full stop-then-start reconfiguration; this wraps a failure during the Shutdown phase of that cycle (see 397/398). The new configuration is never started when this returns.","triggerScenarios":"s.Shutdown(ctx) returns a joined web/DNS shutdown error; the service remains stopped and the error propagates to the caller of Refresh.","commonSituations":"Reconfigure under load with too-short timeouts; shutdown races with in-flight requests during SIGHUP/config-change handling.","solutions":["Inspect the wrapped error to see whether web or DNS shutdown failed and why","Retry the refresh once load subsides","Lengthen shutdown deadlines in the service configuration"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := s.Refresh(ctx)\nif err != nil && strings.Contains(err.Error(), \"shutdown failed\") {\n\tctx2, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancel()\n\terr = s.Refresh(ctx2)\n}","preventionTips":["Use a long-lived, generous context for Refresh","Schedule reconfigures during low-traffic windows"],"tags":["refresh","shutdown","reconfiguration"],"backgroundTag":"graceful-shutdown-timeout","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}