{"record":{"id":"afcad7b19593209c","repo":"SigNoz/signoz","slug":"errcodeservicefailed","errorCode":"ErrCodeServiceFailed","errorMessage":"service %q failed before becoming healthy","messagePattern":"service %q failed before becoming healthy","errorType":"error_code","errorClass":null,"httpStatus":500,"severity":"critical","filePath":"pkg/factory/registry.go","lineNumber":184,"sourceCode":"\t\t}\n\t}\n\n\treturn errors.Join(errs...)\n}\n\n// AwaitHealthy blocks until all services reach the RUNNING state or any service fails.\nfunc (registry *Registry) AwaitHealthy(ctx context.Context) error {\n\tfor _, ss := range registry.services {\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tcase <-ss.healthyC:\n\t\tcase <-ss.startReturnedC:\n\t\t\tss.mu.RLock()\n\t\t\terr := ss.startErr\n\t\t\tss.mu.RUnlock()\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrapf(err, errors.TypeInternal, ErrCodeServiceFailed, \"service %q failed before becoming healthy\", ss.service.Name())\n\t\t\t}\n\t\t\treturn errors.Newf(errors.TypeInternal, ErrCodeServiceFailed, \"service %q terminated before becoming healthy\", ss.service.Name())\n\t\t}\n\t}\n\treturn nil\n}\n\n// ServicesByState returns a snapshot of the current state of all services.\nfunc (registry *Registry) ServicesByState() map[State][]Name {\n\tresult := make(map[State][]Name)\n\tfor _, ss := range registry.services {\n\t\tstate := ss.getState()\n\t\tresult[state] = append(result[state], ss.service.Name())\n\t}\n\treturn result\n}\n\n// IsHealthy returns true if all services are in the RUNNING state.","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/factory/registry.go#L166-L202","documentation":"Thrown by the service registry's AwaitHealthy when a service's Start() returned an error (startErr) before the healthy signal fired. It distinguishes a startup failure from a silent termination (which gets the 'terminated' variant), wrapping the original start error with ErrCodeServiceFailed.","triggerScenarios":"Calling AwaitHealthy(ctx) on a registered service whose Start() blocked, then returned an error — e.g. a HTTP server failing to bind its port, a worker failing to connect to its broker, or a migrator failing before signaling healthy.","commonSituations":"Port already in use (EADDRINUSE) for the service's listener; required dependency (DB, Kafka) unavailable at boot; invalid service configuration causing immediate start failure; startup ordering issues where a dependent service starts before its dependency is healthy.","solutions":["Read the wrapped startErr — it contains the actual startup failure; fix that first","Check for port conflicts and required dependency availability before starting the service","Use DependsOn/dependency ordering so prerequisites become healthy first","Add startup retries/backoff for dependency connection failures at boot"],"exampleFix":"// before\nif err := ss.AwaitHealthy(ctx); err != nil { panic(err) }\n\n// after\nif err := ss.AwaitHealthy(ctx); err != nil {\n\tif errors.Is(err, registry.ErrCodeServiceFailed) {\n\t\tlog.Errorw(\"service failed to start\", \"service\", name, \"startErr\", errors.Unwrap(err))\n\t}\n\treturn err\n}","handlingStrategy":"try-catch","validationCode":"// pre-flight: ensure dependencies are reachable before Start()\nif err := db.Ping(); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := ss.AwaitHealthy(ctx); err != nil {\n\treturn fmt.Errorf(\"bootstrap failed: %w\", err) // wrapped startErr has the cause\n}","preventionTips":["Always inspect the wrapped start error, not just the wrapper","Bind ports only after checking availability","Order service startup with DependsOn so dependencies are healthy first"],"tags":["lifecycle","startup","service-registry","health-check","bootstrap"],"backgroundTag":"service-startup-failure","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}