{"record":{"id":"de2c65079d255f53","repo":"cilium/cilium","slug":"failed-to-convert-subscriberv4innermap-fd-to-ebpf","errorCode":null,"errorMessage":"failed to convert SubscriberV4InnerMap FD to *ebpf.Map: %w","messagePattern":"failed to convert SubscriberV4InnerMap FD to \\*ebpf\\.Map: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/maps/multicast/subscribermap.go","lineNumber":175,"sourceCode":"\tvar val GroupV4Val\n\n\tkey, err := NewGroupV4KeyFromNetIPAddr(group)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = m.Map.Lookup(key.Group, &val)\n\tif errors.Is(err, ebpf.ErrKeyNotExist) {\n\t\treturn nil, fmt.Errorf(\"multicast group %s does not exist: %w\", group.String(), err)\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to query for multicast group: %w\", err)\n\t}\n\n\tvar subMap *ebpf.Map\n\tsubMap, err = ebpf.MapFromID(m.logger, int(val.FD))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to convert SubscriberV4InnerMap FD to *ebpf.Map: %w\", err)\n\t}\n\n\treturn &SubscriberV4InnerMap{subMap}, nil\n}\n\nfunc (m GroupV4OuterMap) Delete(group netip.Addr) error {\n\tkey, err := NewGroupV4KeyFromNetIPAddr(group)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn m.Map.Delete(key)\n}\n\n// List returns a list of all multicast groups in the map. Batch lookup is used to get the groups if supported.\n// Batch lookup is supported in kernel version 5.19 and later for map.HashOfMaps\nfunc (m GroupV4OuterMap) List() ([]netip.Addr, error) {\n\tif m.batchLookupSupported {\n\t\treturn m.ListBatch()","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/maps/multicast/subscribermap.go#L157-L193","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nsubMap, err = ebpf.MapFromID(m.logger, int(val.FD))\nif err != nil {\n    return nil, fmt.Errorf(\"failed to convert SubscriberV4InnerMap FD to *ebpf.Map: %w\", err)\n}\n// after\nsubMap, err = ebpf.MapFromID(m.logger, int(val.FD))\nif err != nil {\n    // stale inner-map FD: recreate the group entry\n    if derr := m.Delete(group); derr != nil { return nil, derr }\n    return nil, fmt.Errorf(\"stale inner map FD for group %s: %w\", group, err)\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"subMap, err := outerMap.Lookup(group)\nif err != nil {\n    if isStaleFD(err) {\n        if derr := outerMap.Delete(group); derr == nil {\n            return outerMap.Lookup(group) // recreate path\n        }\n    }\n    return err\n}","preventionTips":["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"],"tags":["ebpf","file-descriptor","inner-map","race-condition"],"backgroundTag":"stale-ebpf-fd","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}