{"record":{"id":"780e810d8d076ad1","repo":"nats-io/nats-server","slug":"no-flow-response","errorCode":null,"errorMessage":"no flow response","messagePattern":"no flow response","errorType":"http","errorClass":null,"httpStatus":408,"severity":"warning","filePath":"server/jetstream_api.go","lineNumber":4677,"sourceCode":"\t\tcase <-inch:\n\t\t\t// The receiver appears to have gone away.\n\t\t\tsnapshotErr = errors.New(\"no interest\")\n\t\t\thdr = []byte(\"NATS/1.0 408 No Interest\\r\\n\\r\\n\")\n\t\t\tgoto done\n\t\tcase err, ok := <-errCh:\n\t\t\tif !ok {\n\t\t\t\t// Channel closed normally, e.g. on completion.\n\t\t\t\terrCh = nil\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// The snapshotting goroutine has failed for some reason.\n\t\t\tsnapshotErr = err\n\t\t\thdr = fmt.Appendf(nil, \"NATS/1.0 500 %s\\r\\n\\r\\n\", err)\n\t\t\tgoto done\n\t\tcase <-ackTimer.C:\n\t\t\t// It's taking a very long time for the receiver to send us acks,\n\t\t\t// they have probably stalled or there is high loss on the link.\n\t\t\tsnapshotErr = errors.New(\"no flow response\")\n\t\t\thdr = []byte(\"NATS/1.0 408 No Flow Response\\r\\n\\r\\n\")\n\t\t\tgoto done\n\t\t}\n\t\tn, err := io.ReadFull(r, chunk)\n\t\tchunk := chunk[:n]\n\t\tif err != nil {\n\t\t\tif n > 0 {\n\t\t\t\tmset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, nil, chunk, nil, 0))\n\t\t\t}\n\t\t\tselect {\n\t\t\tcase err, ok := <-errCh:\n\t\t\t\tif ok {\n\t\t\t\t\tsnapshotErr = err\n\t\t\t\t\thdr = fmt.Appendf(nil, \"NATS/1.0 500 %s\\r\\n\\r\\n\", err)\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t}\n\t\t\tbreak","sourceCodeStart":4659,"sourceCodeEnd":4695,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/jetstream_api.go#L4659-L4695","documentation":"During a JetStream snapshot the receiver must ack each chunk so the server can pace in-flight chunks. If no ack arrives within snapshotAckTimeout the server assumes the receiver stalled or the link is lossy, aborts the snapshot and returns 408 'No Flow Response'.","triggerScenarios":"The receiving client stops processing chunks (blocked consumer, slow sink, GC pause) without sending acks; ack messages are lost after a connection interruption; snapshotAckTimeout elapses between chunk sends on a large/slow snapshot.","commonSituations":"Backing up a very large stream over a high-latency/lossy link; overloaded or paused receiver process; flow-control acks dropped after NATS client reconnect; undersized reader buffers stalling the ack loop.","solutions":["Fix the receiver so it acks every chunk promptly (drain the snapshot reader continuously).","Retry the snapshot on a stable, low-latency connection after repairing the link.","Reduce per-snapshot size (snapshot more often) or tune chunking for the network path.","Check receiver health (CPU, memory, blocking I/O) before retrying."],"exampleFix":"// before: receiver stalls doing heavy work between reads, acks stop\nfor chunk := range snapshotChunks {\n\theavyBlockingTransform(chunk) // -> 408 no flow response\n}\n// after: keep draining so acks keep flowing\nfor chunk := range snapshotChunks {\n\tselect {\n\tcase sink <- chunk:\n\tcase <-ctx.Done():\n\t\treturn ctx.Err()\n\t}\n}","handlingStrategy":"retry","validationCode":"// ensure the receiver can drain and ack before starting\nnc.SetErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) {\n\tlog.Printf(\"nats error during snapshot: %v\", err)\n})","typeGuard":"func isNoFlowResponse(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"no flow response\")\n}","tryCatchPattern":"err := snapshotStream(js, \"ORDERS\", w)\nif isNoFlowResponse(err) {\n\tif receiverHealthy() {\n\t\treturn snapshotStream(js, \"ORDERS\", w) // stall was transient\n\t}\n\treturn fmt.Errorf(\"receiver stalled during snapshot: %w\", err)\n}","preventionTips":["Drain snapshot chunks continuously; never block between reads on the receiving side.","Watch receiver CPU/GC pauses that can exceed the ack deadline.","Snapshot large streams over low-loss links or in smaller pieces.","Alert on reconnects/subscription loss during backups."],"tags":["jetstream","snapshot","timeout","flow-control","network"],"backgroundTag":"ack-timeout","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}