cilium/cilium · error
DeleteIpamIPFailureCode
DeleteIpamIPFailureCode
Error message
IP is in use by endpoint %d
What it means
The DELETE /ipam/IP handler refuses to release an IP currently assigned to an endpoint. It checks EndpointManager.LookupIPv4/LookupIPv6 first and returns a DeleteIpamIPFailureCode API error naming the owning endpoint ID.
Source
Thrown at pkg/ipam/api/ipam_api_handler.go:141
return nodeRouterAddressing, nil
}
// Handle incoming address allocation requests for the daemon.
func (r *IpamPostIpamIPHandler) Handle(params ipamapi.PostIpamIPParams) middleware.Responder {
owner := swag.StringValue(params.Owner)
pool := ipam.Pool(swag.StringValue(params.Pool))
if err := r.IPAM.AllocateIPString(params.IP, owner, pool); err != nil {
return api.Error(ipamapi.PostIpamIPFailureCode, err)
}
return ipamapi.NewPostIpamIPOK()
}
func (r *IpamDeleteIpamIPHandler) Handle(params ipamapi.DeleteIpamIPParams) middleware.Responder {
// Release of an IP that is in use is not allowed
if ep := r.EndpointManager.LookupIPv4(params.IP); ep != nil {
return api.Error(ipamapi.DeleteIpamIPFailureCode, fmt.Errorf("IP is in use by endpoint %d", ep.ID))
}
if ep := r.EndpointManager.LookupIPv6(params.IP); ep != nil {
return api.Error(ipamapi.DeleteIpamIPFailureCode, fmt.Errorf("IP is in use by endpoint %d", ep.ID))
}
ip, err := netip.ParseAddr(params.IP)
if err != nil {
return api.Error(ipamapi.DeleteIpamIPInvalidCode, fmt.Errorf("Invalid IP address %s: %w", params.IP, err))
}
pool := ipam.Pool(swag.StringValue(params.Pool))
if err := r.IPAM.ReleaseIP(ip, pool); err != nil {
return api.Error(ipamapi.DeleteIpamIPFailureCode, err)
}
return ipamapi.NewDeleteIpamIPOK()
}
View on GitHub (pinned to ac7b90affa)
Solutions
- Release the IP only after the owning endpoint is deleted (delete the pod or wait for termination to complete)
- Verify the endpoint ID in the error and confirm whether it is truly stale; remove the endpoint via the API if it is orphaned
- Find a different free IP if you only need a replacement address
Example fix
// before curl -X DELETE .../ipam/IP?ip=10.0.1.5 # fails: in use by endpoint 1234 // after # 1) remove/confirm the endpoint is gone kubectl delete pod my-pod # or wait for its CNI DELETE to complete # 2) then release the IP curl -X DELETE .../ipam/IP?ip=10.0.1.5
Defensive patterns
Strategy: try-catch
Validate before calling
// Client-side check before DELETE (approximate):
// list endpoints and ensure none uses the IP
func ipInUse(eps []EndpointInfo, ip string) bool {
for _, e := range eps {
if e.IPv4 == ip || e.IPv6 == ip { return true }
}
return false
} Try / catch
resp, err := client.DeleteIpamIP(ip)
if err != nil && strings.Contains(err.Error(), "IP is in use by endpoint") {
return skipOrDeleteEndpointFirst(ip) // parse endpoint ID from message
}
return err Prevention
- Release IPs only through the normal CNI/endpoint teardown flow
- Check endpoint listings before manual IP cleanup
- Handle the 'in use' response as expected behavior, not a bug
When it happens
Trigger: DELETE /ipam/IP for an IP bound to a running pod/endpoint; operators cleaning up 'stale' IPs that are actually in use; releasing an IP while its endpoint is terminating but not yet removed.
Common situations: Manual cleanup scripts freeing pod CIDR IPs that collide with live workloads; buggy controllers double-releasing IPs; CNI DELETE racing endpoint teardown.
Related errors
- failed to get local node: %w
- PatchEndpointIDFailedCode
- unable to parse endpoint parameters: %w
- endpoint ID %d already exists
- IP %s is already in use
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/ec687804bce079fd.
Report an issue: GitHub.