{"record":{"id":"a8b4c7ebf796d91a","repo":"nats-io/nats-server","slug":"stream-missing","errorCode":null,"errorMessage":"stream missing","messagePattern":"stream missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/jetstream_cluster.go","lineNumber":1086,"sourceCode":"\tcase !node.Healthy():\n\t\treturn errors.New(\"group node unhealthy\")\n\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// isConsumerHealthy will determine if the consumer is up to date.\n// For R1 it will make sure the consunmer is present on this server.\nfunc (js *jetStream) isConsumerHealthy(mset *stream, consumer string, ca *consumerAssignment) error {\n\tjs.mu.RLock()\n\tif ca != nil && ca.unsupported != nil {\n\t\tjs.mu.RUnlock()\n\t\treturn nil\n\t}\n\tif mset == nil {\n\t\tjs.mu.RUnlock()\n\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)","sourceCodeStart":1068,"sourceCodeEnd":1104,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream_cluster.go#L1068-L1104","documentation":"This error is produced by jetStream.isConsumerHealthy, the JetStream health-check routine that verifies each consumer is present and healthy on this server. It means the health check was invoked for a consumer whose parent stream (*stream) is nil on this server, so the consumer cannot even be looked up. In practice this indicates the server is being asked to report health for a consumer whose stream no longer exists (or has not yet materialized) locally, typically transiently during cluster topology changes or shutdown.","triggerScenarios":"Health check (/jsz HEALTH or monitor endpoint) iterates assignments and calls isConsumerHealthy while mset (the local stream) is nil for that assignment — e.g. the stream was deleted or its assignment exists but the local stream object has not been created yet during meta/asset replication, or a race during server shutdown.","commonSituations":"NATS servers running with -js_enable_health_check (or /jsz?health=true) reporting 'stream missing' during rolling restarts; stream deletion racing a periodic health check; a new server joining the cluster and being probed before its stream assets materialize.","solutions":["Check whether the stream was deleted or renamed; recreate the stream if it should exist.","Treat it as transient during cluster reconfiguration: wait for the assignment to settle and re-run the health check.","Check server logs for stream deletion/creation events around the error time to identify the racing operation.","If persistent, restart the server so JetStream recovers assignments from the meta layer, or file an issue if it never clears."],"exampleFix":"// before: health check errors while stream is not yet materialized\n// after: gate the health check on stream presence / retry after replication\nif mset == nil {\n    if time.Since(ca.Created) < 5*time.Second {\n        return nil // stream not materialized yet, give it time\n    }\n    return errors.New(\"stream missing\")\n}","handlingStrategy":"retry","validationCode":"// Verify stream exists before trusting/acting on health output\nst, err := js.StreamInfo(streamName)\nif err != nil || st == nil {\n    // stream missing locally; wait for replication or recreate\n}\n","typeGuard":null,"tryCatchPattern":"// Go: treat as transient during topology changes\nif err := srvHealth(ctx); err != nil {\n    if strings.Contains(err.Error(), \"stream missing\") {\n        time.Sleep(2 * time.Second)\n        return retryHealth(ctx)\n    }\n    return err\n}","preventionTips":["Avoid deleting streams while health checks run","Serialize topology changes (delete/recreate) outside of monitoring windows","Poll /jsz?health=true only after new servers have converged","Alert on persistent (not transient) occurrences only"],"tags":["jetstream","nats","health-check","clustering"],"backgroundTag":"jetstream-health-check-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}