nats-io/nats-server · warning
stream import already exists
Error message
stream import already exists
What it means
ErrStreamImportDuplicate is returned when a stream import is a duplicate of one that already exists on the account — isStreamImportDuplicate detects an existing import from the same account with the same subject (from), and the server refuses to add it twice.
Source
Thrown at server/errors.go:144
ErrAccountExpired = errors.New("account expired")
// ErrNoAccountResolver is returned when we attempt an update but do not have an account resolver.
ErrNoAccountResolver = errors.New("account resolver missing")
// ErrAccountResolverUpdateTooSoon is returned when we attempt an update too soon to last request.
ErrAccountResolverUpdateTooSoon = errors.New("account resolver update too soon")
// ErrAccountResolverSameClaims is returned when same claims have been fetched.
ErrAccountResolverSameClaims = errors.New("account resolver no new claims")
// ErrStreamImportAuthorization is returned when a stream import is not authorized.
ErrStreamImportAuthorization = errors.New("stream import not authorized")
// ErrStreamImportBadPrefix is returned when a stream import prefix contains wildcards.
ErrStreamImportBadPrefix = errors.New("stream import prefix can not contain wildcard tokens")
// ErrStreamImportDuplicate is returned when a stream import is a duplicate of one that already exists.
ErrStreamImportDuplicate = errors.New("stream import already exists")
// ErrServiceImportAuthorization is returned when a service import is not authorized.
ErrServiceImportAuthorization = errors.New("service import not authorized")
// ErrImportFormsCycle is returned when an import would form a cycle.
ErrImportFormsCycle = errors.New("import forms a cycle")
// ErrCycleSearchDepth is returned when we have exceeded our maximum search depth..
ErrCycleSearchDepth = errors.New("search cycle depth exhausted")
// ErrClientOrRouteConnectedToGatewayPort represents an error condition when
// a client or route attempted to connect to the Gateway port.
ErrClientOrRouteConnectedToGatewayPort = errors.New("attempted to connect to gateway port")
// ErrWrongGateway represents an error condition when a server receives a connect
// request from a remote Gateway with a destination name that does not match the server's
// Gateway's name.
ErrWrongGateway = errors.New("wrong gateway")View on GitHub (pinned to 3a66a489d2)
Solutions
- Check whether the import already exists (iterate acc.streamImports or track in app state) before calling AddStreamImport
- Treat ErrStreamImportDuplicate as a success case (idempotent import) in setup/reload code
- Remove the existing import first (RemoveStreamImport) if the intent is to replace it, then re-add
- Deduplicate import definitions across config files/claims before applying them
Example fix
// before
importAcc.AddStreamImport(fooAcc, "test", "") // second time -> ErrStreamImportDuplicate
// after
if err := importAcc.AddStreamImport(fooAcc, "test", ""); err != nil && !errors.Is(err, ErrStreamImportDuplicate) {
return err // duplicates are tolerated as idempotent
} Defensive patterns
Strategy: try-catch
Validate before calling
// check existing imports before adding
for _, im := range acc.streamImports {
if im.fr == fromAccount && im.to == fromSubject { return nil /* already imported */ }
} Type guard
func hasStreamImport(acc *Account, from *Account, subject string) bool {
acc.mu.RLock(); defer acc.mu.RUnlock()
for _, im := range acc.streamImports {
if im.fr == from && im.to.Subject == subject { return true }
}
return false
} Try / catch
if err := acc.AddStreamImport(fromAcc, subject, tok); err != nil {
if errors.Is(err, ErrStreamImportDuplicate) { return nil } // idempotent re-add
} Prevention
- Make import setup idempotent — treat duplicates as success on reloads
- Track applied imports in app state to skip re-adding
- Remove-then-add when the intent is to replace an existing import
When it happens
Trigger: Calling AddStreamImport with the same (from account, from subject) pair that is already registered (accounts.go:2784), e.g. re-adding import "test" from fooAcc as in TestMultipleStreamImportsWithSameSubject / accounts_test.go:2676 after a prior import was allowed.
Common situations: Idempotency assumptions — code that adds imports on every config reload without checking existence; retries after a partial failure re-adding the import; multiple config sources defining the same import; tests asserting duplicate detection.
Related errors
- service missing
- account resolver missing
- account jwt not found
- subject has exceeded number of tokens limit
- attempted to connect to route port
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/3827cb6e118c7b5a.
Report an issue: GitHub.