{"record":{"id":"b8b45feb436cd033","repo":"kubernetes/kubernetes","slug":"user-error-more-than-one-job-is-selecting-pods-wi","errorCode":null,"errorMessage":"user error! more than one job is selecting pods with labels: %+v","messagePattern":"user error! more than one job is selecting pods with labels: %\\+v","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/controller/job/job_controller.go","lineNumber":372,"sourceCode":"\t\t\twait.UntilWithContext(ctx, jm.worker, time.Second)\n\t\t})\n\t\twg.Go(func() {\n\t\t\twait.UntilWithContext(ctx, jm.orphanWorker, time.Second)\n\t\t})\n\t}\n\t<-ctx.Done()\n}\n\n// getPodJobs returns a list of Jobs that potentially match a Pod.\nfunc (jm *Controller) getPodJobs(pod *v1.Pod) []*batch.Job {\n\tjobs, err := jm.jobLister.GetPodJobs(pod)\n\tif err != nil {\n\t\treturn nil\n\t}\n\tif len(jobs) > 1 {\n\t\t// ControllerRef will ensure we don't do anything crazy, but more than one\n\t\t// item in this list nevertheless constitutes user error.\n\t\tutilruntime.HandleError(fmt.Errorf(\"user error! more than one job is selecting pods with labels: %+v\", pod.Labels))\n\t}\n\tret := make([]*batch.Job, 0, len(jobs))\n\tfor i := range jobs {\n\t\tret = append(ret, &jobs[i])\n\t}\n\treturn ret\n}\n\n// resolveControllerRef returns the controller referenced by a ControllerRef,\n// or nil if the ControllerRef could not be resolved to a matching controller\n// of the correct Kind.\nfunc (jm *Controller) resolveControllerRef(namespace string, controllerRef *metav1.OwnerReference) *batch.Job {\n\t// We can't look up by UID, so look up by Name and then verify UID.\n\t// Don't even try to look up by Name if it's the wrong Kind.\n\tif controllerRef.Kind != controllerKind.Kind {\n\t\treturn nil\n\t}\n\tjob, err := jm.jobLister.Jobs(namespace).Get(controllerRef.Name)","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/kubernetes/kubernetes/blob/b882c60b4023bdf09264c2d5d30a2cadebc240fb/pkg/controller/job/job_controller.go#L354-L390","documentation":"Logged (utilruntime.HandleError, non-fatal) in `getPodJobs` when a pod's labels match more than one Job's selector (job_controller.go:369-373). ControllerRef disambiguates actual ownership, so this is flagged as user error, not a hard failure — but it indicates ambiguous selectors that can cause pods to be adopted/released unpredictably and breaks the Job uniqueness contract (a pod should be selectable by at most one Job).","triggerScenarios":"Two Jobs with overlapping `spec.selector.matchLabels`/`matchExpressions` such that the same pod satisfies both; a Job using a broad label like `app=web` shared across workloads; manual pod creation matching multiple selectors.","commonSituations":"Template-generated Jobs reusing `app=<chart>` as selector; migrating Job selectors;helm charts deploying sibling Jobs with identical selectors; users copying Job specs and forgetting to uniquify selectors.","solutions":["Give each Job a unique selector scoped to itself, e.g. `matchLabels: {job-name: <name>}` or controller-generated `controller-uid`.","Audit overlapping selectors: `kubectl get jobs -o yaml | grep -A5 selector`.","Set `selector.matchLabels` to a label unique to the Job and ensure pods carry it.","Avoid broad shared labels (`app`, `tier`) as the sole selector key."],"exampleFix":"# before: two jobs share the same selector\napiVersion: batch/v1\nkind: Job\nmetadata: {name: ingest}\nspec:\n  selector:\n    matchLabels: {app: pipeline}\n---\napiVersion: batch/v1\nkind: Job\nmetadata: {name: transform}\nspec:\n  selector:\n    matchLabels: {app: pipeline}\n# after: per-job unique selectors\napiVersion: batch/v1\nkind: Job\nmetadata: {name: ingest, labels: {job-name: ingest}}\nspec:\n  selector:\n    matchLabels: {job-name: ingest}\n  template:\n    metadata: {labels: {job-name: ingest}}","handlingStrategy":"validation","validationCode":"// Verify no two Jobs in a namespace have overlapping selectors before applying.\nfunc selectorsOverlap(a, b metav1.LabelSelector) (bool, error) {\n    sa, err := metav1.LabelSelectorAsSelector(&a)\n    if err != nil { return false, err }\n    sb, err := metav1.LabelSelectorAsSelector(&b)\n    if err != nil { return false, err }\n    // Overlap if there exists a label set matching both; cheap heuristic via intersection of requirements.\n    return sa.String() == sb.String(), nil // exact-match heuristic\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a unique per-Job selector (e.g. `controller-uid` or `job-name`).","Never reuse broad shared labels (`app`, `tier`) as the sole selector.","Lint Job selectors in CI before applying.","Let the API default the selector (auto-generated `controller-uid`) when possible."],"tags":["kubernetes","job-controller","label-selector","misconfiguration","controllerref"],"analyzedSha":"b882c60b4023bdf09264c2d5d30a2cadebc240fb","analyzedAt":"2026-08-07T04:07:48.144Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}