kubernetes/kops · error
error building dns scope: %v
Error message
error building dns scope: %v
What it means
NewNodeController wraps any failure from dnsContext.CreateScope("node") with this message. CreateScope fails only when a scope named "node" already exists, so this indicates the node scope was already created on the same DNSContext — the node watcher is being constructed twice or shares a context with prior initialization.
Source
Thrown at dns-controller/pkg/watchers/node.go:49
kopsutil "k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/upup/pkg/fi/utils"
)
// NodeController watches for nodes
//
// Unlike other watchers, NodeController only creates alias records referenced by records from other controllers
type NodeController struct {
util.Stoppable
client kubernetes.Interface
scope dns.Scope
haveType map[dns.RecordType]bool
}
// NewNodeController creates a NodeController
func NewNodeController(client kubernetes.Interface, dnsContext dns.Context, internalRecordTypes []dns.RecordType) (*NodeController, error) {
scope, err := dnsContext.CreateScope("node")
if err != nil {
return nil, fmt.Errorf("error building dns scope: %v", err)
}
c := &NodeController{
client: client,
scope: scope,
haveType: map[dns.RecordType]bool{},
}
for _, recordType := range internalRecordTypes {
c.haveType[recordType] = true
}
return c, nil
}
// Run starts the NodeController.
func (c *NodeController) Run() {
klog.Infof("starting node controller")View on GitHub (pinned to 4c8573c808)
Solutions
- Ensure initializeWatchers runs once per DNSController
- Construct a fresh DNSController if watchers must be reinitialized
- Check the wrapped %v cause for "duplicate scope" and find the earlier CreateScope("node") call site
- Use a distinct scope name for any custom node DNS records
Example fix
// before dnsContext := dns.NewDNSController(...) NewNodeController(client, dnsContext, types) NewNodeController(client, dnsContext, types) // duplicate // after nodeCtl := NewNodeController(client, dnsContext, types) // single instance owns the "node" scope
Defensive patterns
Strategy: try-catch
Validate before calling
var watchersOnce sync.Once
func ensureWatchers(client kubernetes.Interface, dnsCtx dns.Context, types []dns.RecordType) error {
var err error
watchersOnce.Do(func() { err = initializeWatchers(client, dnsCtx, types) })
return err
} Try / catch
ctl, err := watchers.NewNodeController(client, dnsContext, internalTypes)
if err != nil {
if strings.Contains(err.Error(), "duplicate scope") {
return nil // node watcher already running on this context
}
return fmt.Errorf("starting node watcher: %w", err)
} Prevention
- Call initializeWatchers once per DNSController lifetime (sync.Once)
- Reserve the "node" scope for the built-in node controller; use unique names for custom recorders
- On restart, construct a new DNSController instead of reusing the old context
When it happens
Trigger: initializeWatchers calls NewNodeController on a DNSContext that already has a "node" scope — duplicate initializeWatchers invocation, or another component created the "node" scope first.
Common situations: Calling initializeWatchers twice (reload path, test double-setup); constructing both a custom node recorder and the built-in node controller against one DNSController; reusing a DNSController after a failed previous start.
Related errors
- error building dns scope: %v
- error initializing DNS cache: %v
- duplicate scope: %q
- DNS not implemented on azureCloud
- applying patch to node: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/aa8e3a9f18d5e3fe.
Report an issue: GitHub.