{"record":{"id":"de6b4a155c1f1d8c","repo":"hibiken/asynq","slug":"asynq-the-server-is-in-the-stopped-state-waiting","errorCode":null,"errorMessage":"asynq: the server is in the stopped state. Waiting for shutdown.","messagePattern":"asynq: the server is in the stopped state\\. Waiting for shutdown\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server.go","lineNumber":712,"sourceCode":"\tsrv.syncer.start(&srv.wg)\n\tsrv.recoverer.start(&srv.wg)\n\tsrv.forwarder.start(&srv.wg)\n\tsrv.processor.start(&srv.wg)\n\tsrv.janitor.start(&srv.wg)\n\tsrv.aggregator.start(&srv.wg)\n\treturn nil\n}\n\n// Checks server state and returns an error if pre-condition is not met.\n// Otherwise it sets the server state to active.\nfunc (srv *Server) start() error {\n\tsrv.state.mu.Lock()\n\tdefer srv.state.mu.Unlock()\n\tswitch srv.state.value {\n\tcase srvStateActive:\n\t\treturn fmt.Errorf(\"asynq: the server is already running\")\n\tcase srvStateStopped:\n\t\treturn fmt.Errorf(\"asynq: the server is in the stopped state. Waiting for shutdown.\")\n\tcase srvStateClosed:\n\t\treturn ErrServerClosed\n\t}\n\tsrv.state.value = srvStateActive\n\treturn nil\n}\n\n// Shutdown gracefully shuts down the server.\n// It gracefully closes all active workers. The server will wait for\n// active workers to finish processing tasks for duration specified in Config.ShutdownTimeout.\n// If worker didn't finish processing a task during the timeout, the task will be pushed back to Redis.\nfunc (srv *Server) Shutdown() {\n\tsrv.state.mu.Lock()\n\tif srv.state.value == srvStateNew || srv.state.value == srvStateClosed {\n\t\tsrv.state.mu.Unlock()\n\t\t// server is not running, do nothing and return.\n\t\treturn\n\t}","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/hibiken/asynq/blob/d135f1439bee74e989b7f9b41ecd542cc87f024a/server.go#L694-L730","documentation":"Server.start checks the server state machine: when the state is Stopped (Stop was called, but the server has not been ShutDown/closed), a new Start is rejected with this error because the server is draining and awaiting final shutdown.","triggerScenarios":"Calling srv.Start(handler) or srv.Run(handler) after srv.Stop() but before srv.ShutDown(); attempting to resume processing from the Stopped state.","commonSituations":"Pause/resume logic that assumes Stop is reversible; graceful-restart code calling Stop then immediately Start; signal handlers that call Stop and then try to bring the server back up.","solutions":["After Stop, the only valid next steps are ShutDown (graceful) — plan restarts by creating a new Server instance.","Replace Stop-then-Start patterns with Stop for graceful drain followed by full ShutDown and server re-creation.","Track your own state flag so Start is never called while draining.","If you only need to temporarily halt processing, gate your handler logic instead of using Stop."],"exampleFix":"// before\nsrv.Stop()\nsrv.Start(handler) // error: stopped state\n// after\nsrv.Stop()\nsrv.ShutDown()\n// create a fresh server to restart\nsrv2 := asynq.NewServer(redisOpt, cfg)\nsrv2.Start(handler)","handlingStrategy":"validation","validationCode":"type ServerState int\nconst (StateNew ServerState = iota; StateRunning; StateStopped; StateClosed)\nif state == StateStopped {\n    return errors.New(\"server is stopping; cannot Start until ShutDown completes\")\n}","typeGuard":null,"tryCatchPattern":"if err := srv.Start(handler); err != nil {\n    if strings.Contains(err.Error(), \"stopped state\") {\n        return nil // draining; ignore\n    }\n    return err\n}","preventionTips":["Treat Stop as one-way toward ShutDown; never call Start after Stop.","Implement restarts as: ShutDown old server → create new Server → Start.","Gate temporary pauses at the handler level instead of using Stop."],"tags":["go","asynq","lifecycle","state-machine"],"backgroundTag":"invalid-state-transition","analyzedSha":"d135f1439bee74e989b7f9b41ecd542cc87f024a","analyzedAt":"2026-09-07T19:02:34.660Z","contentChangedAt":"2026-09-07T19:02:34.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}