{"record":{"id":"4d2fb2f28e902cb1","repo":"cilium/cilium","slug":"device-s-is-already-allocated-for-pod-s-by-anoth","errorCode":null,"errorMessage":"device %s is already allocated for pod %s by another claim","messagePattern":"device (.+?) is already allocated for pod (.+?) by another claim","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/networkdriver/dra.go","lineNumber":230,"sourceCode":"\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\treturn errors.Join(errs...)\n}\n\nfunc (driver *Driver) prepareResourceClaim(ctx context.Context, claim *resourceapi.ResourceClaim) kubeletplugin.PrepareResult {\n\tif len(claim.Status.ReservedFor) != 1 {\n\t\treturn kubeletplugin.PrepareResult{\n\t\t\tErr: fmt.Errorf(\"%w: Status.ReservedFor field has more than one entry\", errUnexpectedInput),\n\t\t}\n\t}\n\n\tpod := claim.Status.ReservedFor[0]\n\n\t// Reject devices that are already claimed by a *different* claim for this pod.\n\tif dev := driver.conflictingDeviceForPod(pod.UID, claim.UID, claim.Status.Allocation.Devices.Results); dev != \"\" {\n\t\treturn kubeletplugin.PrepareResult{\n\t\t\tErr: fmt.Errorf(\"device %s is already allocated for pod %s by another claim\", dev, pod.Name),\n\t\t}\n\t}\n\n\tdeviceClaimConfigs, err := driver.deviceClaimConfigs(ctx, claim)\n\tif err != nil {\n\t\treturn kubeletplugin.PrepareResult{Err: err}\n\t}\n\n\tif err := validatePodIfNames(claim, deviceClaimConfigs); err != nil {\n\t\treturn kubeletplugin.PrepareResult{Err: err}\n\t}\n\n\t// Precompute what is already done so retries skip completed work.\n\tstate := driver.newClaimPrepState(pod, claim)\n\n\tvar (\n\t\talloc         []allocation\n\t\tdevicesStatus []resourceapi.AllocatedDeviceStatus","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/networkdriver/dra.go#L212-L248","documentation":"During DRA PrepareResourceClaims, the driver checks via conflictingDeviceForPod whether any device requested by this claim is already allocated to the same pod by a *different* ResourceClaim. If so, preparation is rejected because one pod cannot receive the same network device/interface through two competing claims. This protects the pod's network namespace from double-attachment and conflicting interface names.","triggerScenarios":"Two ResourceClaims allocated by this DRA driver both request the same device and are both reserved for the same pod UID; prepareResourceClaim runs for the second claim and conflictingDeviceForPod returns the conflicting device name.","commonSituations":"A pod spec references two claims that overlap in requested devices (e.g. duplicated device requests in two DeviceClasses/claims); an old claim was not unprepared and a replacement claim for the same pod re-requests the same device; scheduler allocated overlapping claims because ResourceSlice filters were too permissive.","solutions":["Ensure each pod requests each device through only one claim; remove the overlapping device request from the duplicate claim.","Unprepare/delete the stale claim holding the device for this pod so the conflict clears, then retry preparation.","Tighten the driver's Allocation/ResourceSlice filters (or CEL allocatedDeviceSelectors) so the scheduler cannot allocate the same device to two claims of one pod.","If the pod was recreated (same name, new UID), delete the leftover claim referencing the old UID so the device table entry is freed."],"exampleFix":"// before: pod references two claims that both request net-device eth0\nresources:\n  claims:\n    - name: net-a  # requests device0\n    - name: net-b  # also requests device0\n// after: make requests disjoint\nresources:\n  claims:\n    - name: net-a  # requests device0\n    - name: net-b  # requests device1","handlingStrategy":"validation","validationCode":"// Before submitting claims for a pod, assert no device is requested twice:\nfunc noOverlappingDevices(claims []*resourceapi.ResourceClaim) error {\n  seen := map[string]string{} // device -> claim name\n  for _, c := range claims {\n    if c.Status.Allocation == nil { continue }\n    for _, r := range c.Status.Allocation.Devices.Results {\n      if prev, dup := seen[r.Device]; dup {\n        return fmt.Errorf(\"device %s requested by claims %s and %s\", r.Device, prev, c.Name)\n      }\n      seen[r.Device] = c.Name\n    }\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":"if res := driver.PrepareResourceClaims(...); res.Err != nil {\n  if strings.Contains(res.Err.Error(), \"already allocated for pod\") {\n    // inspect claims ReservedFor this pod, unprepare the stale claim, retry once\n  }\n}","preventionTips":["Keep a 1:1 mapping of device requests to a single claim per pod","Use CEL allocatedDeviceSelectors so the scheduler cannot hand the same device to two claims of one pod","Delete leftover claims when recreating pods to avoid stale UIDs holding devices"],"tags":["kubernetes","dra","device-allocation","conflict"],"backgroundTag":"device-already-claimed-conflict","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}