cilium/cilium · error
failed to convert SubscriberV4InnerMap FD to *ebpf.Map: %w
Error message
failed to convert SubscriberV4InnerMap FD to *ebpf.Map: %w
What it means
After finding the group's value (a struct holding an inner-map FD), Lookup converts that FD back to an *ebpf.Map with ebpf.MapFromID. This error is returned when the FD is stale, invalid, or does not refer to an existing map. It means the outer map's value references an inner map that no longer exists.
Source
Thrown at pkg/maps/multicast/subscribermap.go:175
var val GroupV4Val
key, err := NewGroupV4KeyFromNetIPAddr(group)
if err != nil {
return nil, err
}
err = m.Map.Lookup(key.Group, &val)
if errors.Is(err, ebpf.ErrKeyNotExist) {
return nil, fmt.Errorf("multicast group %s does not exist: %w", group.String(), err)
}
if err != nil {
return nil, fmt.Errorf("failed to query for multicast group: %w", err)
}
var subMap *ebpf.Map
subMap, err = ebpf.MapFromID(m.logger, int(val.FD))
if err != nil {
return nil, fmt.Errorf("failed to convert SubscriberV4InnerMap FD to *ebpf.Map: %w", err)
}
return &SubscriberV4InnerMap{subMap}, nil
}
func (m GroupV4OuterMap) Delete(group netip.Addr) error {
key, err := NewGroupV4KeyFromNetIPAddr(group)
if err != nil {
return err
}
return m.Map.Delete(key)
}
// List returns a list of all multicast groups in the map. Batch lookup is used to get the groups if supported.
// Batch lookup is supported in kernel version 5.19 and later for map.HashOfMaps
func (m GroupV4OuterMap) List() ([]netip.Addr, error) {
if m.batchLookupSupported {
return m.ListBatch()View on GitHub (pinned to ac7b90affa)
Solutions
- Retry the Lookup; if it persists, Delete and re-create the group entry so a fresh inner map FD is stored
- Check for concurrent Delete/Insert on the same group and serialize access
- Inspect `bpftool map list` to confirm the inner map ID still exists
- Ensure agent shutdown ordering does not close inner maps before in-flight lookups complete
Example fix
// before
subMap, err = ebpf.MapFromID(m.logger, int(val.FD))
if err != nil {
return nil, fmt.Errorf("failed to convert SubscriberV4InnerMap FD to *ebpf.Map: %w", err)
}
// after
subMap, err = ebpf.MapFromID(m.logger, int(val.FD))
if err != nil {
// stale inner-map FD: recreate the group entry
if derr := m.Delete(group); derr != nil { return nil, derr }
return nil, fmt.Errorf("stale inner map FD for group %s: %w", group, err)
} Defensive patterns
Strategy: retry
Try / catch
subMap, err := outerMap.Lookup(group)
if err != nil {
if isStaleFD(err) {
if derr := outerMap.Delete(group); derr == nil {
return outerMap.Lookup(group) // recreate path
}
}
return err
} Prevention
- Serialize group Insert/Delete/Lookup to avoid racing inner-map teardown
- Recreate group entries when MapFromID fails (stale FD)
- Avoid closing inner maps while lookups may be in flight
When it happens
Trigger: val.FD holds an invalid or closed FD when ebpf.MapFromID(m.logger, int(val.FD)) is called, e.g. inner map deleted between lookup and conversion, or corrupted/stale FD stored in the outer map entry.
Common situations: Race with Delete of the group removing the inner map while another goroutine looks it up; FD reuse/corruption; agent teardown closed inner maps while lookups still in flight.
Related errors
- getting program from id %d: %w
- opening program with id %d: %w
- opening program with id %d: %w
- %w: identity=%d got rev=%d currentAt=%d, want rev=%d
- check program %d: %w
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/de2c65079d255f53.
Report an issue: GitHub.