cilium/cilium · error
encountered duplicate BGP instance with name %s
Error message
encountered duplicate BGP instance with name %s
What it means
registerOrReconcileDiff rejects a CiliumBGPNodeConfig whose Spec.BGPInstances list contains two entries with the same `name`, because instance names are used as map keys and session identifiers. The diff computation aborts immediately on the first duplicate, so the whole node config is not reconciled.
Source
Thrown at pkg/bgp/manager/workdiff.go:79
fallthrough
case len(wd.reconcile) > 0:
return false
}
return true
}
// registerOrReconcileDiff will populate the `seen` field of the reconcileDiff with `policy`,
// compute BgpServers which must be registered and mark existing BgpServers for
// reconciliation of their configuration.
//
// since registerOrReconcileDiff populates the `seen` field of a diff, this method should always
// be called first when computing a reconcileDiff.
func (wd *reconcileDiff) registerOrReconcileDiff(existingInstances map[string]*instance.BGPInstance, desiredConfig *v2.CiliumBGPNodeConfig) error {
for i, config := range desiredConfig.Spec.BGPInstances {
if _, ok := wd.seen[config.Name]; !ok {
wd.seen[config.Name] = &desiredConfig.Spec.BGPInstances[i]
} else {
return fmt.Errorf("encountered duplicate BGP instance with name %s", config.Name)
}
if existing, ok := existingInstances[config.Name]; !ok {
// new instance
wd.register = append(wd.register, config.Name)
} else {
// existing instance
recreate, err := wd.requiresRecreate(existing, &desiredConfig.Spec.BGPInstances[i])
if err != nil {
return err
}
if recreate {
wd.withdraw = append(wd.withdraw, config.Name)
wd.register = append(wd.register, config.Name) // register does an initial reconciliation as well
} else {
wd.reconcile = append(wd.reconcile, config.Name)
}
}
}View on GitHub (pinned to ac7b90affa)
Solutions
- Edit the CiliumBGPNodeConfig and give every BGPInstances entry a unique `name`.
- Re-apply the CR and confirm the agent log no longer reports the duplicate.
- If generated via Helm/kustomize, fix the template so instance names are parameterized and unique.
- Optionally add a CRD-level validation or admission policy to reject duplicate instance names early.
Example fix
# before bgpInstances: - name: "instance-1" localASN: 65001 - name: "instance-1" localASN: 65002 # after bgpInstances: - name: "instance-1" localASN: 65001 - name: "instance-2" localASN: 65002
Defensive patterns
Strategy: validation
Validate before calling
seen := map[string]struct{}{}
for _, i := range cfg.Spec.BGPInstances {
if _, dup := seen[i.Name]; dup {
return fmt.Errorf("duplicate BGP instance name %q", i.Name)
}
seen[i.Name] = struct{}{}
} Prevention
- Enforce unique instance names via a CRD enum-free but admission-policy check (e.g. ValidatingAdmissionPolicy, CEL uniqueness).
- In Helm/kustomize, generate instance names from a map key so duplicates are impossible.
- Run `kubectl apply --dry-run=server` plus a lint script over BGP configs.
- Review diffs after merging CR changes to catch copy-pasted blocks.
When it happens
Trigger: Iterating desiredConfig.Spec.BGPInstances in registerOrReconcileDiff when wd.seen already contains config.Name — i.e. two YAML/JSON BGPInstances entries with an identical name in one CiliumBGPNodeConfig.
Common situations: Copy-pasting a BGPInstances block and forgetting to change the name; Helm/kustomize templates rendering the same name twice; merging patches that append a duplicate instance instead of replacing it.
Related errors
- virtual router with ASN %d does not exist
- local ASN not set for instance
- metric config validation failed - duplicate metric specified
- cannot configure both static and dynamic Hubble metrics
- invalid peer IP address: %w
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/b709e7f46d15f1b6.
Report an issue: GitHub.