{"record":{"id":"be579b5999103535","repo":"nats-io/nats-server","slug":"js-stream-offline","errorCode":"JS_STREAM_OFFLINE","errorMessage":"stream is offline","messagePattern":"stream is offline","errorType":"error_code","errorClass":"JSStreamOfflineReasonError","httpStatus":null,"severity":"error","filePath":"server/jetstream_api.go","lineNumber":1640,"sourceCode":"\t\tresp.Error = NewJSStreamMismatchError()\n\t\ts.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))\n\t\treturn\n\t}\n\n\t// Handle clustered version here.\n\tif s.JetStreamIsClustered() {\n\t\ts.jsClusteredStreamUpdateRequest(ci, acc, subject, reply, copyBytes(rmsg), &cfg, ncfg.Pedantic)\n\t\treturn\n\t}\n\n\tmset, err := acc.lookupStream(streamName)\n\tif err != nil {\n\t\tresp.Error = NewJSStreamNotFoundError(Unless(err))\n\t\ts.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))\n\t\treturn\n\t}\n\tif mset.offlineReason != _EMPTY_ {\n\t\tresp.Error = NewJSStreamOfflineReasonError(errors.New(mset.offlineReason))\n\t\ts.sendDelayedAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp), nil, errRespDelay)\n\t\treturn\n\t}\n\n\t// Update asset version metadata.\n\tsetStaticStreamMetadata(&cfg)\n\n\tif err := mset.updatePedantic(&cfg, ncfg.Pedantic); err != nil {\n\t\tresp.Error = NewJSStreamUpdateError(err, Unless(err))\n\t\ts.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))\n\t\treturn\n\t}\n\n\tmsetCfg := mset.config()\n\tresp.StreamInfo = &StreamInfo{\n\t\tCreated:   mset.createdTime(),\n\t\tState:     mset.state(),\n\t\tConfig:    *setDynamicStreamMetadata(&msetCfg),","sourceCodeStart":1622,"sourceCodeEnd":1658,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream_api.go#L1622-L1658","documentation":"This JetStream API error (code JS_STREAM_OFFLINE) is returned on a stream info request when the stream exists but has an offlineReason set, meaning it is temporarily unavailable cluster-wide (e.g. created by a migration/restored asset not yet activated). The server responds via NewJSStreamOfflineReasonError wrapping the stream's specific offline reason.","triggerScenarios":"Sending a stream info request ($JS.API.STREAM.INFO.<stream>) for a stream whose mset.offlineReason is non-empty; typically streams restored from backup/snapshot pending activation, or streams whose peers are all offline.","commonSituations":"Querying a stream restored via the restore API before it is activated; running info against a stream whose hosting peers are down; HA failover windows where the stream group has no online peers.","solutions":["Read the underlying offline reason in the API error payload for the specific cause.","Wait for the stream's peers to come online / for restore activation to complete, then retry.","If restored, activate the stream (complete the restore procedure) before issuing requests.","If peers are permanently down, restore quorum or recreate the stream from backup."],"exampleFix":"// before\nsi, err := js.StreamInfo(\"ORDERS\") // JS_STREAM_OFFLINE\n// after\nsi, err := js.StreamInfo(\"ORDERS\")\nif err != nil {\n    var apiErr *nats.APIError\n    if errors.As(err, &apiErr) && apiErr.ErrorCode == nats.JSStreamOffline {\n        // poll/retry until the stream becomes online\n        return waitForStreamOnline(js, \"ORDERS\", timeout)\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"func streamOnline(js nats.JetStreamContext, name string) error {\n    _, err := js.StreamInfo(name)\n    var apiErr *nats.APIError\n    if errors.As(err, &apiErr) && apiErr.ErrorCode == nats.JSStreamOffline {\n        return fmt.Errorf(\"stream %s offline: %s\", name, apiErr.Description)\n    }\n    return err\n}","typeGuard":"func isStreamOffline(err error) bool {\n    var apiErr *nats.APIError\n    return errors.As(err, &apiErr) && apiErr.ErrorCode == nats.JSStreamOffline\n}","tryCatchPattern":"err := retry(3, backoff, func() error {\n    _, err := js.StreamInfo(\"ORDERS\")\n    if isStreamOffline(err) { return err /* retryable */ }\n    return nats.ErrEndOfData /* stop */\n})","preventionTips":["Complete stream restore/activation before serving traffic","Monitor peer liveness of stream groups in clustered mode","Poll StreamInfo until offlineReason clears after failover/restore","Alert on JS_STREAM_OFFLINE responses in client tooling"],"tags":["jetstream","offline","stream","nats-server"],"backgroundTag":"stream-offline","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}