nats-io/nats-server · error
duplicate entry for %q
Error message
duplicate entry for %q
What it means
This function builds weighted cluster/subject mappings (e.g. service imports or weight mappings). It rejects duplicate destination subjects within a single mapping definition: if two destination entries share the same Subject string, it fails with this error naming the duplicated subject.
Source
Thrown at server/accounts.go:808
return a.AddWeightedMappings(src, NewMapDest(dest, 100))
}
// AddWeightedMappings will add in a weighted mappings for the destinations.
func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error {
a.mu.Lock()
defer a.mu.Unlock()
if !IsValidSubject(src) {
return ErrBadSubject
}
m := &mapping{src: src, wc: subjectHasWildcard(src), dests: make([]*destination, 0, len(dests)+1)}
seen := make(map[string]struct{})
var tw = make(map[string]uint8)
for _, d := range dests {
if _, ok := seen[d.Subject]; ok {
return fmt.Errorf("duplicate entry for %q", d.Subject)
}
seen[d.Subject] = struct{}{}
if d.Weight > 100 {
return fmt.Errorf("individual weights need to be <= 100")
}
tw[d.Cluster] += d.Weight
if tw[d.Cluster] > 100 {
return fmt.Errorf("total weight needs to be <= 100")
}
err := ValidateMapping(src, d.Subject)
if err != nil {
return err
}
tr, err := NewSubjectTransform(src, d.Subject)
if err != nil {
return err
}
if d.Cluster == _EMPTY_ {View on GitHub (pinned to 3a66a489d2)
Solutions
- Deduplicate the dests slice by Subject before building the mapping (keep last/first occurrence per policy)
- Find and merge the duplicate source in config (server config, operator config, resolver) so each subject appears once
- If duplicates are intentional (multiple weights), aggregate them into a single entry with summed weights instead of separate entries
Example fix
// before
dests := []Destination{{Subject: "a"}, {Subject: "a"}}
m, err := buildMapping(src, dests) // duplicate entry for "a"
// after
dests = dedupeBySubject(dests)
m, err := buildMapping(src, dests) Defensive patterns
Strategy: validation
Validate before calling
seen := make(map[string]struct{})
for _, d := range dests {
if _, dup := seen[d.Subject]; dup {
return fmt.Errorf("duplicate subject %q in mapping %q", d.Subject, src)
}
seen[d.Subject] = struct{}{}
} Try / catch
m, err := buildMapping(src, dests)
if err != nil {
var dupSubj string
if n, _ := fmt.Sscanf(err.Error(), "duplicate entry for %q", &dupSubj); n == 1 {
return fmt.Errorf("config error: subject %q defined multiple times in mapping", dupSubj)
}
return err
} Prevention
- Deduplicate destination lists when merging config layers
- Validate config at load time before building mappings
- Treat duplicate subjects as a config-load error with file/line info
When it happens
Trigger: Passing a dests slice to the mapping builder where two entries have identical d.Subject values — typically from merging config sources that each contributed the same account/subject, or duplicated entries in server config (accounts/imports/exports lists).
Common situations: Overlapping config snippets (operator config + resolver) that both define the same mapping destination; copy-pasted account import entries; automated config generation concatenating lists without deduplication.
Related errors
- service missing
- account resolver missing
- stream import already exists
- account jwt not found
- ErrBadCryptoStoreProvider
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/15cd1b967d2334a8.
Report an issue: GitHub.