{"record":{"id":"aa8e3a9f18d5e3fe","repo":"kubernetes/kops","slug":"error-building-dns-scope-v-aa8e3a","errorCode":null,"errorMessage":"error building dns scope: %v","messagePattern":"error building dns scope: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dns-controller/pkg/watchers/node.go","lineNumber":49,"sourceCode":"\tkopsutil \"k8s.io/kops/pkg/apis/kops/util\"\n\t\"k8s.io/kops/upup/pkg/fi/utils\"\n)\n\n// NodeController watches for nodes\n//\n// Unlike other watchers, NodeController only creates alias records referenced by records from other controllers\ntype NodeController struct {\n\tutil.Stoppable\n\tclient   kubernetes.Interface\n\tscope    dns.Scope\n\thaveType map[dns.RecordType]bool\n}\n\n// NewNodeController creates a NodeController\nfunc NewNodeController(client kubernetes.Interface, dnsContext dns.Context, internalRecordTypes []dns.RecordType) (*NodeController, error) {\n\tscope, err := dnsContext.CreateScope(\"node\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error building dns scope: %v\", err)\n\t}\n\n\tc := &NodeController{\n\t\tclient:   client,\n\t\tscope:    scope,\n\t\thaveType: map[dns.RecordType]bool{},\n\t}\n\n\tfor _, recordType := range internalRecordTypes {\n\t\tc.haveType[recordType] = true\n\t}\n\n\treturn c, nil\n}\n\n// Run starts the NodeController.\nfunc (c *NodeController) Run() {\n\tklog.Infof(\"starting node controller\")","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/dns-controller/pkg/watchers/node.go#L31-L67","documentation":"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.","triggerScenarios":"initializeWatchers calls NewNodeController on a DNSContext that already has a \"node\" scope — duplicate initializeWatchers invocation, or another component created the \"node\" scope first.","commonSituations":"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.","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"],"exampleFix":"// before\ndnsContext := dns.NewDNSController(...)\nNewNodeController(client, dnsContext, types)\nNewNodeController(client, dnsContext, types) // duplicate\n// after\nnodeCtl := NewNodeController(client, dnsContext, types) // single instance owns the \"node\" scope","handlingStrategy":"try-catch","validationCode":"var watchersOnce sync.Once\nfunc ensureWatchers(client kubernetes.Interface, dnsCtx dns.Context, types []dns.RecordType) error {\n    var err error\n    watchersOnce.Do(func() { err = initializeWatchers(client, dnsCtx, types) })\n    return err\n}","typeGuard":null,"tryCatchPattern":"ctl, err := watchers.NewNodeController(client, dnsContext, internalTypes)\nif err != nil {\n    if strings.Contains(err.Error(), \"duplicate scope\") {\n        return nil // node watcher already running on this context\n    }\n    return fmt.Errorf(\"starting node watcher: %w\", err)\n}","preventionTips":["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"],"tags":["dns","scope","node","initialization"],"backgroundTag":"duplicate-scope-creation","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}