{"record":{"id":"c3eff433da3db64a","repo":"thanos-io/thanos","slug":"invalid-service-state-v-expected-v","errorCode":null,"errorMessage":"invalid service state: %v, expected: %v","messagePattern":"invalid service state: (.+?), expected: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cortex/util/services/basic_service.go","lineNumber":76,"sourceCode":"\n\t// everything below is protected by this mutex\n\tstateMu     sync.RWMutex\n\tstate       State\n\tfailureCase error\n\tlisteners   []chan func(l Listener)\n\tserviceName string\n\n\t// closed when state reaches Running, Terminated or Failed state\n\trunningWaitersCh chan struct{}\n\t// closed when state reaches Terminated or Failed state\n\tterminatedWaitersCh chan struct{}\n\n\tserviceContext context.Context\n\tserviceCancel  context.CancelFunc\n}\n\nfunc invalidServiceStateError(state, expected State) error {\n\treturn fmt.Errorf(\"invalid service state: %v, expected: %v\", state, expected)\n}\n\nfunc invalidServiceStateWithFailureError(state, expected State, failure error) error {\n\treturn fmt.Errorf(\"invalid service state: %v, expected: %v, failure: %w\", state, expected, failure)\n}\n\n// NewBasicService returns service built from three functions (using BasicService).\nfunc NewBasicService(start StartingFn, run RunningFn, stop StoppingFn) *BasicService {\n\treturn &BasicService{\n\t\tstartFn:             start,\n\t\trunningFn:           run,\n\t\tstoppingFn:          stop,\n\t\tstate:               New,\n\t\trunningWaitersCh:    make(chan struct{}),\n\t\tterminatedWaitersCh: make(chan struct{}),\n\t}\n}\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/internal/cortex/util/services/basic_service.go#L58-L94","documentation":"invalidServiceStateError reports that a BasicService (Cortex services framework) was observed in a different lifecycle state than required by StartAsync or awaitState. The message includes the actual state and the expected one, e.g. calling StartAsync on a service that is already running or was terminated.","triggerScenarios":"StartAsync called on a service not in New state; awaitState observed a state transition to anything other than the expected state (e.g., the service failed or was stopped while waiting for Running).","commonSituations":"Double-starting a module by wiring the same service into a module manager twice; a dependency service failing during startup causing dependents to see Failed instead of Running; tests restarting services without proper termination; race between StopAsync and StartAsync.","solutions":["Log/inspect the actual vs expected state in the message; if actual is Failed, find the root cause via invalidServiceStateWithFailureError or service failure logs.","Ensure StartAsync is called exactly once per service instance, from a single owner (module manager).","Use service.Manager / observers to wait for dependencies to reach Running before starting dependents.","Do not call StartAsync after Terminate; create a fresh service instance instead."],"exampleFix":"// before\nsvc.StartAsync(ctx)\nsvc.AwaitRunning(ctx) // panics/errors if svc already started\n// after\nif svc.State() == services.New {\n    svc.StartAsync(ctx)\n    if err := svc.StartAsyncErr(); err != nil { /* handle */ }\n    if err := services.AwaitRunning(ctx, svc); err != nil { /* handle */ }\n}","handlingStrategy":"validation","validationCode":"if svc.State() != services.New {\n    return fmt.Errorf(\"cannot start service in state %v\", svc.State())\n}\nsvc.StartAsync(ctx)","typeGuard":"func canStart(s services.Service) bool { return s.State() == services.New }","tryCatchPattern":"if err := services.AwaitRunning(ctx, svc); err != nil {\n    return fmt.Errorf(\"service did not reach Running: %w\", err)\n}","preventionTips":["Start each service exactly once, from one owner (module manager).","Await dependencies before starting dependents.","Never call StartAsync after Terminate; rebuild the service.","Check svc.State() before lifecycle calls in tests."],"tags":["lifecycle","state-machine","service"],"backgroundTag":"invalid-state-transition","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}