nats-io/nats-server · error
error adding stream: %w
Error message
error adding stream: %w
What it means
After limits checks pass, the server creates the stream in 'restore mode' via addStreamForRestore. If stream creation fails (name conflict, config rejected at store level, storage allocation failure), RestoreStreamV2 wraps the cause. Note: an exact stream-name conflict is detected earlier with JSStreamNameExistRestoreFailedError, so this wrapper usually reflects lower-level store/creation errors.
Source
Thrown at server/stream_backup.go:372
}
return nil
}
reserveCfg := cfg
reserveCfg.MaxBytes = max(reserveCfg.MaxBytes, restoreRemaining)
js.mu.RLock()
err = js.checkAllLimits(&selected, tier, &reserveCfg, reserved, 0)
js.mu.RUnlock()
if err != nil {
return nil, err
}
if err := checkUsageLimits(); err != nil {
return nil, err
}
mset, err := a.addStreamForRestore(&cfg)
if err != nil {
return nil, fmt.Errorf("error adding stream: %w", err)
}
defer func() {
var state StreamState
mset.store.FastState(&state)
mset.mu.Lock()
mset.lseq = state.LastSeq
mset.mu.Unlock()
if err := mset.completeRestore(); err != nil {
if err = fmt.Errorf("failed to activate stream %q: %w", cfg.Name, err); retErr == nil {
retErr = err
}
s.Warnf("JetStream stream restore for '%s > %s' failed to activate stream: %v", a.Name, cfg.Name, err)
}
}()
// Start off at the right sequence number. This is important in particular
// when the backup contains no messages or would restore to no interest.
if _, err = mset.store.Compact(nstate.FirstSeq); err != nil {View on GitHub (pinned to 3a66a489d2)
Solutions
- Read the wrapped cause: if it says stream name already exists, delete the existing stream or restore under a different name
- Check the JetStream store directory permissions and free disk/memory for the stream's storage type
- Ensure no other restore/create for the same stream name is running; retry after the conflicting operation finishes
- Re-run `nats stream info` / check account limits, then retry the restore once resources and naming conflicts are resolved
Example fix
// before: restore without checking target
acc.RestoreStreamV2(cfg, r)
// after: ensure the stream does not already exist and the account has JetStream
if _, err := acc.LookupStream(cfg.Name); err == nil {
return fmt.Errorf("stream %q already exists; delete it first", cfg.Name)
}
acc.RestoreStreamV2(cfg, r) Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := acc.LookupStream(cfg.Name); err == nil {
return fmt.Errorf("stream %q exists; delete before restore", cfg.Name)
}
if err := acc.CheckJetStream(); err != nil {
return err
} Try / catch
mset, err := acc.RestoreStreamV2(cfg, r)
if err != nil {
var nap ErrAPIResponse
if errors.As(err, &nap) {
// inspect wrapped API error (e.g. stream exists / limits) and clean up
}
return fmt.Errorf("restore failed adding stream: %w", err)
} Prevention
- Check for an existing stream with the same name before restoring
- Verify account JetStream limits (memory/store) accommodate the snapshot size
- Avoid concurrent restores of the same stream name
- Ensure store directory permissions and capacity are healthy
When it happens
Trigger: addStreamForRestore fails because the store cannot create the stream: storage engine error (file perms, disk full at FS level), invalid config that slipped past earlier checks (e.g. duplicate subjects handled differently per storage backend), account/stream limits raced with another restore, or the stream was created between the earlier lookupStream check and this call.
Common situations: Two operators restoring the same stream concurrently; a stream with the same name created while the restore request was in flight; disk permissions or full filesystem on the JetStream store directory; restoring into an account whose tier limits were just tightened.
Related errors
- error creating store for stream
- flush of last block failed: %w
- restore for stream '%s > %s' requires reply subject for each
- restore for stream '%s > %s' received short chunk
- 10062
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/8daac0f50127b44f.
Report an issue: GitHub.