{"record":{"id":"7461a63f6baee009","repo":"nats-io/nats-server","slug":"stream-node-missing","errorCode":null,"errorMessage":"stream node missing","messagePattern":"stream node missing","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/jetstream_cluster.go","lineNumber":1050,"sourceCode":"\tmsetNode := mset.raftNode()\n\tmset.cfgMu.RLock()\n\treplicas := mset.cfg.Replicas\n\tmset.cfgMu.RUnlock()\n\tvar nrgWerr error\n\tif node != nil {\n\t\tnrgWerr = node.GetWriteErr()\n\t}\n\tstreamWerr := mset.getWriteErr()\n\tswitch {\n\tcase replicas <= 1:\n\t\treturn nil // No further checks for R=1 streams\n\n\tcase node == nil:\n\t\treturn errors.New(\"group node missing\")\n\n\tcase msetNode == nil:\n\t\t// Can happen when the stream's node is not yet initialized.\n\t\treturn errors.New(\"stream node missing\")\n\n\tcase node != msetNode:\n\t\ts.Warnf(\"Detected stream cluster node skew '%s > %s'\", acc.GetName(), streamName)\n\t\treturn errors.New(\"cluster node skew detected\")\n\n\tcase nrgWerr != nil:\n\t\treturn fmt.Errorf(\"node write error: %v\", nrgWerr)\n\n\tcase streamWerr != nil:\n\t\treturn fmt.Errorf(\"stream write error: %v\", streamWerr)\n\n\tcase !mset.isMonitorRunning():\n\t\treturn errors.New(\"monitor goroutine not running\")\n\n\tcase mset.isCatchingUp():\n\t\treturn errors.New(\"stream catching up\")\n\n\tcase !node.Healthy():","sourceCodeStart":1032,"sourceCodeEnd":1068,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream_cluster.go#L1032-L1068","documentation":"Returned by jetStream.isStreamHealthy when the stream's in-memory stream object exists but its Raft node (mset.raftNode()) is nil, i.e. the replicated stream has not finished initializing its raft peer. The comment notes this can happen while the stream's node is not yet initialized.","triggerScenarios":"HEALTHCHECK on an R>1 stream during the window between stream creation and raft node startup, or after the raft node was torn down (e.g. during stream delete/recreate or failed recovery).","commonSituations":"Querying health immediately after creating a replicated stream; server restart while raft state is reloading; stream recreation race in automation scripts.","solutions":["Retry the health check after the stream finishes initializing","Poll STREAM.INFO until the stream reports ready before running health checks","If it never initializes, check server logs for raft/asset creation errors and restart the server"],"exampleFix":"// before\nhc, _ := nc.Request(\"$JS.API.HEALTHCHECK\", nil, time.Second)\n// after\nwaitForStreamReady(nc, stream, 30*time.Second) // poll STREAM.INFO first\nhc, _ := nc.Request(\"$JS.API.HEALTHCHECK\", nil, time.Second)","handlingStrategy":"retry","validationCode":"// Wait until the replicated stream reports ready before health checks\nwaitForStream := func(nc *nats.Conn, stream string, timeout time.Duration) error {\n    deadline := time.Now().Add(timeout)\n    for time.Now().Before(deadline) {\n        if _, err := nc.Request(fmt.Sprintf(\"$JS.API.STREAM.INFO.%s\", stream), nil, 2*time.Second); err == nil {\n            return nil\n        }\n        time.Sleep(500 * time.Millisecond)\n    }\n    return errors.New(\"stream not ready\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"stream node missing\") {\n    // transient during init; retry with backoff, alert only if persistent\n    time.Sleep(backoff)\n    return healthcheck()\n}","preventionTips":["Add a readiness delay after stream creation proportional to cluster size","Poll STREAM.INFO until the stream is up before health probes","Alert only when the error persists beyond an init window"],"tags":["jetstream","raft","healthcheck","initialization"],"backgroundTag":"jetstream-raft-node-missing","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}