{"record":{"id":"28a62950ecef8e1b","repo":"derailed/k9s","slug":"no-valid-selector-found-on-deployment-s","errorCode":null,"errorMessage":"no valid selector found on deployment: %s","messagePattern":"no valid selector found on deployment: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/dp.go","lineNumber":70,"sourceCode":"\n// Scale a Deployment.\nfunc (d *Deployment) Scale(ctx context.Context, path string, replicas int32) error {\n\treturn scaleRes(ctx, d.getFactory(), client.DpGVR, path, replicas)\n}\n\n// Restart a Deployment rollout.\nfunc (d *Deployment) Restart(ctx context.Context, path string, opts *metav1.PatchOptions) error {\n\treturn restartRes[*appsv1.Deployment](ctx, d.getFactory(), client.DpGVR, path, opts)\n}\n\n// TailLogs tail logs for all pods represented by this Deployment.\nfunc (d *Deployment) TailLogs(ctx context.Context, opts *LogOptions) ([]LogChan, error) {\n\tdp, err := d.GetInstance(opts.Path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif dp.Spec.Selector == nil || len(dp.Spec.Selector.MatchLabels) == 0 {\n\t\treturn nil, fmt.Errorf(\"no valid selector found on deployment: %s\", opts.Path)\n\t}\n\n\treturn podLogs(ctx, dp.Spec.Selector.MatchLabels, opts)\n}\n\n// Pod returns a pod victim by name.\nfunc (d *Deployment) Pod(fqn string) (string, error) {\n\tdp, err := d.GetInstance(fqn)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn podFromSelector(d.Factory, dp.Namespace, dp.Spec.Selector.MatchLabels)\n}\n\n// GetInstance fetch a matching deployment.\nfunc (d *Deployment) GetInstance(fqn string) (*appsv1.Deployment, error) {\n\to, err := d.Factory.Get(d.gvr, fqn, true, labels.Everything())","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/dp.go#L52-L88","documentation":"Deployment.TailLogs (internal/dao/dp.go:62-72) fans out log streaming to all pods a Deployment owns by listing pods via the Deployment's spec.selector.matchLabels. If that selector is nil or has no matchLabels, there is no way to find the pods, so it refuses with this error naming the deployment path.","triggerScenarios":"Calling log-tailing on a Deployment whose spec.selector is missing or whose matchLabels map is empty. This is normally rejected by the API server at create time, so it typically appears for objects created through unusual paths (faulty Helm charts, older API versions, direct etcd manipulation) or already-invalid cached objects.","commonSituations":"Charts that template an empty selector under conditional values; admissions webhooks stripping selectors; resources created before a cluster upgrade tightened validation.","solutions":["Inspect the object: kubectl get deploy <name> -n <ns> -o jsonpath='{.spec.selector}'","Fix the manifest/chart so spec.selector.matchLabels matches the pod template labels and re-apply","As a workaround, tail logs from the pods view directly (pods are listed regardless of the owner's selector)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Guard before tailing: the deployment must expose a usable selector.\nfunc HasSelector(dp *appsv1.Deployment) bool {\n\treturn dp.Spec.Selector != nil && len(dp.Spec.Selector.MatchLabels) > 0\n}","typeGuard":"func SelectableDeployment(dp *appsv1.Deployment) (map[string]string, error) {\n    if dp.Spec.Selector == nil || len(dp.Spec.Selector.MatchLabels) == 0 {\n        return nil, fmt.Errorf(\"no valid selector found on deployment: %s/%s\", dp.Namespace, dp.Name)\n    }\n    return dp.Spec.Selector.MatchLabels, nil\n}","tryCatchPattern":"dp, err := d.GetInstance(path)\nif err != nil { return nil, err }\nif sel, serr := SelectableDeployment(dp); serr == nil {\n    return podLogs(ctx, sel, opts)\n} else {\n    // fallback: tail by the pod template's own labels instead\n    return podLogs(ctx, dp.Spec.Template.Labels, opts)\n}","preventionTips":["Lint deployments in CI: spec.selector.matchLabels must be non-empty and match template labels","Never apply workloads with --validate=false","Audit clusters periodically for selector-less workloads (kyverno/polaris policies)"],"tags":["go","kubernetes","k9s","deployment","selector","labels"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}