{"record":{"id":"075061867febaa09","repo":"cilium/cilium","slug":"inserting-host-endpoint-policy-program-w","errorCode":null,"errorMessage":"inserting host endpoint policy program: %w","messagePattern":"inserting host endpoint policy program: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/datapath/loader/host.go","lineNumber":126,"sourceCode":"\tvar hostObj hostObjects\n\tcommit, cleanup, err := collLoader.LoadAndAssign(ctx, logger, &hostObj, spec, &bpf.CollectionOptions{\n\t\tMapRegistry: reg,\n\t\tCollectionOptions: ebpf.CollectionOptions{\n\t\t\tMaps: ebpf.MapOptions{PinPath: bpf.TCGlobalsPath()},\n\t\t},\n\t\tConstants:      ciliumHostConfiguration(ep, lnc),\n\t\tMapRenames:     ciliumHostMapRenames(ep, lnc),\n\t\tConfigDumpPath: filepath.Join(bpfStateDeviceDir(ep.InterfaceName()), hostEndpointConfig),\n\t}, lnc, attachmentContextHost(ep, host), bpffsDevicePluginPinsTcDir(bpf.CiliumPath(), host))\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer cleanup()\n\tdefer hostObj.Close()\n\n\t// Insert host endpoint policy program.\n\tif err := hostObj.PolicyMap.Update(uint32(ep.GetID()), hostObj.PolicyProg, ebpf.UpdateAny); err != nil {\n\t\treturn fmt.Errorf(\"inserting host endpoint policy program: %w\", err)\n\t}\n\n\t// Attach cil_to_host to cilium_host ingress.\n\tif err := attachSKBProgram(logger, host, hostObj.ToHost, symbolToHostEp,\n\t\tbpffsDeviceLinksDir(bpf.CiliumPath(), host), netlink.HANDLE_MIN_INGRESS, option.Config.EnableTCX); err != nil {\n\t\treturn fmt.Errorf(\"interface %s ingress: %w\", ep.InterfaceName(), err)\n\t}\n\t// Attach cil_from_host to cilium_host egress.\n\tif err := attachSKBProgram(logger, host, hostObj.FromHost, symbolFromHostEp,\n\t\tbpffsDeviceLinksDir(bpf.CiliumPath(), host), netlink.HANDLE_MIN_EGRESS, option.Config.EnableTCX); err != nil {\n\t\treturn fmt.Errorf(\"interface %s egress: %w\", ep.InterfaceName(), err)\n\t}\n\n\tif err := commit(); err != nil {\n\t\treturn fmt.Errorf(\"committing bpf pins: %w\", err)\n\t}\n\n\treturn nil","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/pkg/datapath/loader/host.go#L108-L144","documentation":"attachCiliumHost returns this when updating the host endpoint's policy program into the cilium_call_policy map fails: hostObj.PolicyMap.Update(uint32(ep.GetID()), hostObj.PolicyProg, ebpf.UpdateAny). This map-based tail-call dispatch is how the host endpoint's policy program is reached; a failed update means the program handle could not be inserted (map missing/renamed wrongly, key collision with different type, map full, or fd invalid).","triggerScenarios":"After LoadAndAssign succeeds, the PolicyMap.Update call fails: cilium_policy map renamed to include the endpoint ID doesn't match the compiled spec, the map was not pinned/persisted (PinPath missing), ep.GetID() overflows uint16-derived key or collides, or the program fd is invalid because PolicyProg did not load (verifier error swallowed earlier).","commonSituations":"Upgrades where cilium_policy map layout changed and stale pinned maps are reused; custom map renames registered in ciliumHostRenames conflicting with defaults; running with map pinning enabled but bpffs state directory deleted mid-run; endpoint ID churn producing mismatched map names.","solutions":["Inspect the wrapped ebpf error; if it's EINVAL/ENOENT for the map, remove stale pinned maps under /sys/fs/bpf and restart the agent.","Verify ciliumHostMapRenames produces names matching the compiled bpf_host map names (LocalMapName(cilium_calls/cilium_policy, epID)).","Confirm PolicyProg actually loaded (LoadAndAssign returned nil) and the program type is compatible as a tail-call target.","Ensure ep.GetID() fits the map key type and that the endpoint ID is stable across reloads.","Check kernel >= minimum supported version and program size within verifier complexity limits."],"exampleFix":"// before: stale pinned policy map causes Update to fail silently-looping on reload\n// after: unpin and recreate maps when update fails with ENOENT\nif err := hostObj.PolicyMap.Update(uint32(ep.GetID()), hostObj.PolicyProg, ebpf.UpdateAny); err != nil {\n    if errors.Is(err, os.ErrNotExist) {\n        os.RemoveAll(bpf.TCGlobalsPath()) // clear stale pins, agent restart recreates\n    }\n    return fmt.Errorf(\"inserting host endpoint policy program: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// Validate pinned map state before reload\nfunc policyMapPinned(epID uint16) error {\n    name := bpf.LocalMapName(policymap.MapName, epID)\n    path := filepath.Join(bpf.TCGlobalsPath(), name)\n    if _, err := os.Stat(path); os.IsNotExist(err) {\n        return fmt.Errorf(\"pinned map %s missing at %s; clear stale pins and restart\", name, path)\n    }\n    return nil\n}","typeGuard":"func isMapUpdateError(err error) bool {\n    var eebpf *ebpf.LoadError // or check wrapped errors from ebpf map ops\n    _ = eebpf\n    return errors.Is(err, unix.EINVAL) || errors.Is(err, unix.ENOENT) ||\n        errors.Is(err, unix.ENOSPC)\n}","tryCatchPattern":"if err := reload(); err != nil {\n    if strings.Contains(err.Error(), \"inserting host endpoint policy program\") {\n        if errors.Is(err, unix.ENOENT) {\n            // stale pin: recreate maps\n            cleanupStalePins(bpf.TCGlobalsPath())\n            retryWithBackoff(reload)\n            return\n        }\n        log.Error(\"policy program insert failed\", \"detail\", errors.Unwrap(err))\n    }\n}","preventionTips":["Clear pinned maps when upgrading between Cilium versions with map layout changes.","Keep map renames consistent with compiled bpf_host map names.","Ensure bpffs pin path exists and is writable before starting the agent.","Avoid reusing endpoint IDs across restarts without map cleanup."],"tags":["ebpf","bpf-map","cilium","tail-call","policy"],"backgroundTag":"bpf-map-update-failed","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}