{"record":{"id":"18f90dd7b28c41a1","repo":"nsqio/nsq","slug":"e-req-failed","errorCode":"E_REQ_FAILED","errorMessage":"exiting","messagePattern":"exiting","errorType":"exception","errorClass":"ClientErr","httpStatus":null,"severity":"error","filePath":"nsqd/channel.go","lineNumber":453,"sourceCode":"//\n// `timeoutMs` == 0 - requeue a message immediately\n// `timeoutMs`  > 0 - asynchronously wait for the specified timeout\n//\n//\tand requeue a message (aka \"deferred requeue\")\nfunc (c *Channel) RequeueMessage(clientID int64, id MessageID, timeout time.Duration) error {\n\t// remove from inflight first\n\tmsg, err := c.popInFlightMessage(clientID, id)\n\tif err != nil {\n\t\treturn err\n\t}\n\tc.removeFromInFlightPQ(msg)\n\tatomic.AddUint64(&c.requeueCount, 1)\n\n\tif timeout == 0 {\n\t\tc.exitMutex.RLock()\n\t\tif c.Exiting() {\n\t\t\tc.exitMutex.RUnlock()\n\t\t\treturn errors.New(\"exiting\")\n\t\t}\n\t\terr := c.put(msg)\n\t\tc.exitMutex.RUnlock()\n\t\treturn err\n\t}\n\n\t// deferred requeue\n\treturn c.StartDeferredTimeout(msg, timeout)\n}\n\n// AddClient adds a client to the Channel's client list\nfunc (c *Channel) AddClient(clientID int64, client Consumer) error {\n\tc.exitMutex.RLock()\n\tdefer c.exitMutex.RUnlock()\n\n\tif c.Exiting() {\n\t\treturn errors.New(\"exiting\")\n\t}","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/nsqio/nsq/blob/85cf10c09c6c3c86160d6f0eb156f62d0efc1648/nsqd/channel.go#L435-L471","documentation":"Channel.RequeueMessage handles a REQ with timeout 0 by immediately re-putting the message into the channel queue. Under exitMutex it first checks Exiting(): once the channel has been told to exit (topic/channel deleted via the HTTP API, empty-and-close, or nsqd shutdown) no further state mutation is allowed and it returns errors.New(\"exiting\"). The TCP protocol layer wraps this as a non-fatal E_REQ_FAILED ('REQ <id> failed exiting') response to the client.","triggerScenarios":"A consumer sends REQ <id> 0 at the same moment the channel is being deleted: DELETE /channel/delete?topic=t&channel=c, DELETE /topic/delete, or nsqd draining during shutdown. The message was already popped from the in-flight map, so the REQ cannot be honored and the client gets E_REQ_FAILED.","commonSituations":"Ops runbooks that delete/recreate channels or topics while consumers are live; rolling redeployments that empty channels; consumers with long max-requeue-timeouts racing a channel teardown; nsqd graceful shutdown with connected stragglers.","solutions":["Treat E_REQ_FAILED ... 'exiting' as terminal for that channel: stop REQ-retrying and let the client disconnect/reconnect.","Resubscribe after reconnect - if the channel was merely deleted it is recreated on SUB, and the message was already requeued server-side.","Coordinate: pause the channel (POST /channel/pause) before deleting so consumers stop receiving, avoiding the race.","During nsqd shutdown, CLS/close consumer connections before deleting channels."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// consumer side (go-nsq style): inspect the error frame from REQ\nerr := consumer.HandleReq(id, timeout) // or your raw-command wrapper\nif err != nil {\n\tif strings.Contains(err.Error(), \"E_REQ_FAILED\") && strings.Contains(err.Error(), \"exiting\") {\n\t\t// channel/topic is being deleted or nsqd is shutting down: stop retrying,\n\t\t// the message was already requeued server-side\n\t\treturn errStopConsuming\n\t}\n\treturn err\n}","preventionTips":["Pause channels before deleting them (POST /channel/pause?topic=t&channel=c) so REQ/SUB races cannot occur.","Make consumers treat any E_*_FAILED containing 'exiting' as a reconnect signal, not a data error.","Avoid running channel/topic deletion automation while consumers are actively subscribed."],"tags":["nsq","nsqd","protocol","lifecycle","concurrency"],"backgroundTag":null,"analyzedSha":"85cf10c09c6c3c86160d6f0eb156f62d0efc1648","analyzedAt":"2026-08-16T00:53:05.009Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}