{"record":{"id":"50ce4bee91ea7eac","repo":"nats-io/nats-server","slug":"consumer-assignment-error-w","errorCode":null,"errorMessage":"consumer assignment error: %w","messagePattern":"consumer assignment error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/jetstream_cluster.go","lineNumber":1104,"sourceCode":"\t\treturn errors.New(\"stream missing\")\n\t}\n\ts, cc := js.srv, js.cluster\n\tif cc == nil {\n\t\t// Non-clustered mode\n\t\tjs.mu.RUnlock()\n\t\treturn nil\n\t}\n\tif ca == nil || ca.Group == nil {\n\t\tjs.mu.RUnlock()\n\t\treturn errors.New(\"consumer assignment or group missing\")\n\t}\n\t// Surface any persisted assignment-level error (e.g. failed create on this\n\t// peer) so the health check reflects the broken state instead of falling\n\t// through to runtime-only checks.\n\tif ca.err != nil {\n\t\terr := ca.err\n\t\tjs.mu.RUnlock()\n\t\treturn fmt.Errorf(\"consumer assignment error: %w\", err)\n\t}\n\tcreated := ca.Created\n\tnode := ca.Group.node\n\tjs.mu.RUnlock()\n\n\t// Check if not running at all.\n\to := mset.lookupConsumer(consumer)\n\tif o == nil {\n\t\tif time.Since(created) < 5*time.Second {\n\t\t\t// No further checks, consumer is not available yet but should be soon.\n\t\t\t// We'll start erroring once we're sure this consumer is actually broken.\n\t\t\treturn nil\n\t\t}\n\t\treturn errors.New(\"consumer not found\")\n\t}\n\n\toNode := o.raftNode()\n\trc, _ := o.replica()","sourceCodeStart":1086,"sourceCodeEnd":1122,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream_cluster.go#L1086-L1122","documentation":"During the consumer portion of a JetStream health check, the consumer assignment (ca) carries a persisted assignment-level error (ca.err) — for example the consumer failed to be created on this peer (limits, invalid config). The health check surfaces this error instead of falling through to runtime checks on a consumer that never started, so the consumer reports unhealthy.","triggerScenarios":"Consumer create/update proposal failed on a peer and the error was persisted in the consumer assignment; consumer created with a config the peer cannot honor (e.g. deliver subject doesn't exist on that server version, account limits); leader election moved to a peer holding the failed assignment.","commonSituations":"Exceeded MaxConsumers or related account limits; DURABLE consumer config conflict across versions; partially failed consumer creation after network partition during setup.","solutions":["Unwrap the error to see the root cause (limits, invalid config) and fix it — e.g. delete unused consumers to free MaxConsumers quota, correct the consumer config","Re-issue the consumer create/update via the JS API so the assignment error clears","Check that all peers run compatible server versions for the consumer features used","Review server logs on the peer that originally rejected the consumer for the exact failure reason"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"ci, err := js.ConsumerInfo(stream, consumer)\nif err != nil { /* consumer never materialized: inspect assignment error via healthz/jsz */ }\n","typeGuard":"func hasConsumerAssignmentErr(err error) bool {\n    return strings.Contains(err.Error(), \"consumer assignment error\")\n}\n","tryCatchPattern":"if err := healthz(); err != nil {\n    cause := errors.Unwrap(err)\n    log.Printf(\"consumer assignment unhealthy: %v\", cause) // fix root cause (limits/config)\n}\n","preventionTips":["Track MaxConsumers usage and clean up idle/ephemeral consumers","Validate consumer configs against the server version in use","Re-issue consumer creation after cluster partitions to clear stale assignment errors"],"tags":["jetstream","consumers","health-check","consumer-assignment"],"backgroundTag":"jetstream-consumer-unhealthy","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}