{"record":{"id":"8d06a6f40e295493","repo":"derailed/k9s","slug":"no-valid-selector-found-on-daemonset-q","errorCode":null,"errorMessage":"no valid selector found on daemonset %q","messagePattern":"no valid selector found on daemonset %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/ds.go","lineNumber":65,"sourceCode":"\t}\n\n\treturn render.ExtractImages(&ds.Spec.Template.Spec), nil\n}\n\n// Restart a DaemonSet rollout.\nfunc (d *DaemonSet) Restart(ctx context.Context, path string, opts *metav1.PatchOptions) error {\n\treturn restartRes[*appsv1.DaemonSet](ctx, d.getFactory(), client.DsGVR, path, opts)\n}\n\n// TailLogs tail logs for all pods represented by this DaemonSet.\nfunc (d *DaemonSet) TailLogs(ctx context.Context, opts *LogOptions) ([]LogChan, error) {\n\tds, err := d.GetInstance(opts.Path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif ds.Spec.Selector == nil || len(ds.Spec.Selector.MatchLabels) == 0 {\n\t\treturn nil, fmt.Errorf(\"no valid selector found on daemonset %q\", opts.Path)\n\t}\n\n\treturn podLogs(ctx, ds.Spec.Selector.MatchLabels, opts)\n}\n\nfunc podLogs(ctx context.Context, sel map[string]string, opts *LogOptions) ([]LogChan, error) {\n\tf, ok := ctx.Value(internal.KeyFactory).(*watch.Factory)\n\tif !ok {\n\t\treturn nil, errors.New(\"expecting a context factory\")\n\t}\n\tls, err := metav1.ParseToLabelSelector(toSelector(sel))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlsel, err := metav1.LabelSelectorAsSelector(ls)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/ds.go#L47-L83","documentation":"DaemonSet.TailLogs (internal/dao/ds.go:58-68) locates a DaemonSet's pods through spec.selector.matchLabels to fan out log streams. If the selector is nil or matchLabels is empty, pod discovery is impossible and it refuses with this error naming the DaemonSet path.","triggerScenarios":"Tail-logs on a DaemonSet whose spec.selector is absent or has an empty matchLabels map - an object that is invalid by current API validation but can exist via permissive creation paths (old charts, webhooks, direct API writes bypassing validation).","commonSituations":"Templated Helm charts with conditionally-empty selectors; DaemonSets created against very old API versions; malformed manifests applied with --validate=false.","solutions":["Inspect: kubectl get ds <name> -n <ns> -o jsonpath='{.spec.selector}'","Repair the selector to match the pod template labels and re-apply","Workaround: tail logs from the pods view, or select pods manually by the template's own labels"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Guard before tailing: the daemonset must expose a usable selector.\nfunc HasSelector(ds *appsv1.DaemonSet) bool {\n\treturn ds.Spec.Selector != nil && len(ds.Spec.Selector.MatchLabels) > 0\n}","typeGuard":"func SelectableDaemonSet(ds *appsv1.DaemonSet) (map[string]string, error) {\n    if ds.Spec.Selector == nil || len(ds.Spec.Selector.MatchLabels) == 0 {\n        return nil, fmt.Errorf(\"no valid selector found on daemonset %q\", ds.Name)\n    }\n    return ds.Spec.Selector.MatchLabels, nil\n}","tryCatchPattern":"ds, err := d.GetInstance(opts.Path)\nif err != nil { return nil, err }\nif sel, serr := SelectableDaemonSet(ds); serr == nil {\n    return podLogs(ctx, sel, opts)\n} else {\n    return podLogs(ctx, ds.Spec.Template.Labels, opts) // fallback via template labels\n}","preventionTips":["Enforce non-empty selectors with admission policy (Kyverno rule on apps/v1 DaemonSet)","Chart authors: unit-test rendered selectors against empty values","Tail from the pods view when a DaemonSet is known-broken"],"tags":["go","kubernetes","k9s","daemonset","selector","labels"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}