{"record":{"id":"3827cb6e118c7b5a","repo":"nats-io/nats-server","slug":"stream-import-already-exists","errorCode":null,"errorMessage":"stream import already exists","messagePattern":"stream import already exists","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/errors.go","lineNumber":144,"sourceCode":"\tErrAccountExpired = errors.New(\"account expired\")\n\n\t// ErrNoAccountResolver is returned when we attempt an update but do not have an account resolver.\n\tErrNoAccountResolver = errors.New(\"account resolver missing\")\n\n\t// ErrAccountResolverUpdateTooSoon is returned when we attempt an update too soon to last request.\n\tErrAccountResolverUpdateTooSoon = errors.New(\"account resolver update too soon\")\n\n\t// ErrAccountResolverSameClaims is returned when same claims have been fetched.\n\tErrAccountResolverSameClaims = errors.New(\"account resolver no new claims\")\n\n\t// ErrStreamImportAuthorization is returned when a stream import is not authorized.\n\tErrStreamImportAuthorization = errors.New(\"stream import not authorized\")\n\n\t// ErrStreamImportBadPrefix is returned when a stream import prefix contains wildcards.\n\tErrStreamImportBadPrefix = errors.New(\"stream import prefix can not contain wildcard tokens\")\n\n\t// ErrStreamImportDuplicate is returned when a stream import is a duplicate of one that already exists.\n\tErrStreamImportDuplicate = errors.New(\"stream import already exists\")\n\n\t// ErrServiceImportAuthorization is returned when a service import is not authorized.\n\tErrServiceImportAuthorization = errors.New(\"service import not authorized\")\n\n\t// ErrImportFormsCycle is returned when an import would form a cycle.\n\tErrImportFormsCycle = errors.New(\"import forms a cycle\")\n\n\t// ErrCycleSearchDepth is returned when we have exceeded our maximum search depth..\n\tErrCycleSearchDepth = errors.New(\"search cycle depth exhausted\")\n\n\t// ErrClientOrRouteConnectedToGatewayPort represents an error condition when\n\t// a client or route attempted to connect to the Gateway port.\n\tErrClientOrRouteConnectedToGatewayPort = errors.New(\"attempted to connect to gateway port\")\n\n\t// ErrWrongGateway represents an error condition when a server receives a connect\n\t// request from a remote Gateway with a destination name that does not match the server's\n\t// Gateway's name.\n\tErrWrongGateway = errors.New(\"wrong gateway\")","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/errors.go#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nimportAcc.AddStreamImport(fooAcc, \"test\", \"\") // second time -> ErrStreamImportDuplicate\n// after\nif err := importAcc.AddStreamImport(fooAcc, \"test\", \"\"); err != nil && !errors.Is(err, ErrStreamImportDuplicate) {\n\treturn err // duplicates are tolerated as idempotent\n}","handlingStrategy":"try-catch","validationCode":"// check existing imports before adding\nfor _, im := range acc.streamImports {\n\tif im.fr == fromAccount && im.to == fromSubject { return nil /* already imported */ }\n}","typeGuard":"func hasStreamImport(acc *Account, from *Account, subject string) bool {\n\tacc.mu.RLock(); defer acc.mu.RUnlock()\n\tfor _, im := range acc.streamImports {\n\t\tif im.fr == from && im.to.Subject == subject { return true }\n\t}\n\treturn false\n}","tryCatchPattern":"if err := acc.AddStreamImport(fromAcc, subject, tok); err != nil {\n\tif errors.Is(err, ErrStreamImportDuplicate) { return nil } // idempotent re-add\n}","preventionTips":["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"],"tags":["nats","server","configuration","duplicate-import"],"backgroundTag":"duplicate-resource","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}