{"record":{"id":"ade59e60173089a4","repo":"nats-io/nats-server","slug":"unable-to-delete-consumer-q-for-session-q-v","errorCode":null,"errorMessage":"unable to delete consumer %q for session %q: %v","messagePattern":"unable to delete consumer %q for session %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/mqtt.go","lineNumber":3483,"sourceCode":"\tif sess.pubRelConsumer != nil {\n\t\tpubRelDur = sess.pubRelConsumer.Durable\n\t}\n\n\tsess.subs = nil\n\tsess.pendingPublish = nil\n\tsess.pendingPubRel = nil\n\tsess.cpending = nil\n\tsess.pubRelConsumer = nil\n\tsess.seq = 0\n\tsess.tmaxack = 0\n\t// Discarded session: reset the PI counter too so a reused session object\n\t// does not inherit the previous session's identifiers. Spec [MQTT-3.1.2-6].\n\tsess.last_pi = 0\n\tsess.mu.Unlock()\n\n\tfor _, dur := range durs {\n\t\tif _, err := sess.jsa.deleteConsumer(mqttStreamName, dur, noWait); isErrorOtherThan(err, JSConsumerNotFoundErr) {\n\t\t\treturn fmt.Errorf(\"unable to delete consumer %q for session %q: %v\", dur, sess.id, err)\n\t\t}\n\t}\n\tif pubRelDur != _EMPTY_ {\n\t\t_, err := sess.jsa.deleteConsumer(mqttOutStreamName, pubRelDur, noWait)\n\t\tif isErrorOtherThan(err, JSConsumerNotFoundErr) {\n\t\t\treturn fmt.Errorf(\"unable to delete consumer %q for session %q: %v\", pubRelDur, sess.id, err)\n\t\t}\n\t}\n\n\tif seq > 0 {\n\t\terr := sess.jsa.deleteMsg(mqttSessStreamName, seq, !noWait)\n\t\t// Ignore the various errors indicating that the message (or sequence)\n\t\t// is already deleted, can happen in a cluster.\n\t\tif isErrorOtherThan(err, JSSequenceNotFoundErrF) {\n\t\t\tif isErrorOtherThan(err, JSStreamMsgDeleteFailedF) || !strings.Contains(err.Error(), ErrStoreMsgNotFound.Error()) {\n\t\t\t\treturn fmt.Errorf(\"unable to delete session %q record at sequence %v: %v\", id, seq, err)\n\t\t\t}\n\t\t}","sourceCodeStart":3465,"sourceCodeEnd":3501,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/mqtt.go#L3465-L3501","documentation":"Wraps an error from deleting a durable JetStream consumer associated with an MQTT session on the '$MQTT' stream. Consumer-not-found is tolerated (JSConsumerNotFoundErr is exempt); any other delete failure is wrapped with the consumer name and session ID.","triggerScenarios":"sess.jsa.deleteConsumer(mqttStreamName, dur, noWait) returns an error other than JSConsumerNotFoundErr during session teardown — timeout, no responders, stream missing, or API failure.","commonSituations":"JetStream unavailable during client disconnect; cluster quorum lost; stream '$MQTT' deleted or renamed; slow/no-wait delete racing with a busy server.","solutions":["Verify JetStream and the '$MQTT' stream are healthy on the server","Retry the disconnect/cleanup once the cluster is stable","Manually delete the orphaned durable consumer (nats consumer info/rm $MQTT <dur>) if cleanup keeps failing","Check for clock/latency issues causing delete timeouts"],"exampleFix":"// before\n// disconnect fails: unable to delete consumer\n// after\nnats con rm $MQTT <durable-name>  // manual cleanup after restoring JetStream health\nnull","handlingStrategy":"try-catch","validationCode":"// Pre-check that the stream and its consumers are reachable\nconst streams = await fetch('http://monitor:8222/jsz?consumers=true').then(r=>r.json())\nconst mqttStream = streams.account_details?.flatMap(a=>a.streams||[]).find(s=>s.name==='$MQTT')\nif (!mqttStream) console.warn('$MQTT stream missing; disconnect cleanup will fail')","typeGuard":null,"tryCatchPattern":"try {\n  await client.disconnect()\n} catch (e) {\n  if (String(e).includes('unable to delete consumer')) {\n    // orphaned durable; clean up manually once JetStream is healthy\n    await natsAdmin.consumerDelete('$MQTT', durableName)\n  } else { throw e }\n}","preventionTips":["Ensure JetStream is healthy during disconnects/restarts","Don't delete or rename internal $MQTT streams","Gracefully disconnect clients before server maintenance","Periodically list durable consumers and remove orphans"],"tags":["mqtt","jetstream","consumer","cleanup"],"backgroundTag":"jetstream-consumer-delete-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}