nats-io/nats-server · error

restore for stream '%s > %s' is stalled

Error message

restore for stream '%s > %s' is stalled

What it means

JetStream stream restore inactivity timeout. During a restore the server arms an activity timer; if no new chunk arrives within the interval, the restore is considered stalled and is cancelled with this error.

Source

Thrown at server/jetstream_api.go:4434

				restoreDone = true
				restoreResult = rr
				if inputDone {
					err := inputErr
					if err == nil {
						err = rr.err
					}
					finish(replySubj, err, rr.mset)
					return
				}
			case <-activeQ.ch:
				if n, ok := activeQ.popOne(); ok {
					total += n
					if !inputDone {
						notActive.Reset(activityInterval)
					}
				}
			case <-notActive.C:
				err := fmt.Errorf("restore for stream '%s > %s' is stalled", acc.Name, streamName)
				closeWithError(err)
				doneCh <- err
				return
			}
		}
	})

	return doneCh
}

// Process a snapshot request.
func (s *Server) jsStreamSnapshotRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
	if c == nil || !s.JetStreamEnabled() {
		return
	}
	ci, acc, hdr, msg, err := s.getRequestInfo(c, rmsg)
	if err != nil {
		s.Warnf(badAPIRequestT, msg)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Ensure the client keeps sending chunks continuously or restarts the restore on failure
  2. Increase throughput / reduce per-chunk processing time on the client; read the file in a tight loop
  3. Check network stability between client and server; retry the restore after a failure
Defensive patterns

Strategy: retry

Validate before calling

// ensure a fast, uninterrupted chunk producer before starting
if !canReadFileContinuously(restoreFile) {
	return fmt.Errorf("restore source must supply chunks without long pauses")
}

Try / catch

err := restoreStream(cfg, r)
if err != nil && strings.Contains(err.Error(), "is stalled") {
	// restart restore; resume/checkpoint if supported
	return restoreStream(cfg, reopenReader())
}

Prevention

When it happens

Trigger: Client stops sending chunks (crash, slow producer, network partition) without closing the restore session, leaving the notActive timer to fire after activityInterval.

Common situations: Client application killed mid-restore; WAN/slow link where chunk generation takes longer than the inactivity window; back-pressure from client-side file reading pauses exceeding the interval.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/175468ff554c8e4b. Report an issue: GitHub.