cilium/cilium · error

inserting host endpoint policy program: %w

Error message

inserting host endpoint policy program: %w

What it means

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).

Source

Thrown at pkg/datapath/loader/host.go:126

	var hostObj hostObjects
	commit, cleanup, err := collLoader.LoadAndAssign(ctx, logger, &hostObj, spec, &bpf.CollectionOptions{
		MapRegistry: reg,
		CollectionOptions: ebpf.CollectionOptions{
			Maps: ebpf.MapOptions{PinPath: bpf.TCGlobalsPath()},
		},
		Constants:      ciliumHostConfiguration(ep, lnc),
		MapRenames:     ciliumHostMapRenames(ep, lnc),
		ConfigDumpPath: filepath.Join(bpfStateDeviceDir(ep.InterfaceName()), hostEndpointConfig),
	}, lnc, attachmentContextHost(ep, host), bpffsDevicePluginPinsTcDir(bpf.CiliumPath(), host))
	if err != nil {
		return err
	}
	defer cleanup()
	defer hostObj.Close()

	// Insert host endpoint policy program.
	if err := hostObj.PolicyMap.Update(uint32(ep.GetID()), hostObj.PolicyProg, ebpf.UpdateAny); err != nil {
		return fmt.Errorf("inserting host endpoint policy program: %w", err)
	}

	// Attach cil_to_host to cilium_host ingress.
	if err := attachSKBProgram(logger, host, hostObj.ToHost, symbolToHostEp,
		bpffsDeviceLinksDir(bpf.CiliumPath(), host), netlink.HANDLE_MIN_INGRESS, option.Config.EnableTCX); err != nil {
		return fmt.Errorf("interface %s ingress: %w", ep.InterfaceName(), err)
	}
	// Attach cil_from_host to cilium_host egress.
	if err := attachSKBProgram(logger, host, hostObj.FromHost, symbolFromHostEp,
		bpffsDeviceLinksDir(bpf.CiliumPath(), host), netlink.HANDLE_MIN_EGRESS, option.Config.EnableTCX); err != nil {
		return fmt.Errorf("interface %s egress: %w", ep.InterfaceName(), err)
	}

	if err := commit(); err != nil {
		return fmt.Errorf("committing bpf pins: %w", err)
	}

	return nil

View on GitHub (pinned to ac7b90affa)

Solutions

  1. 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.
  2. Verify ciliumHostMapRenames produces names matching the compiled bpf_host map names (LocalMapName(cilium_calls/cilium_policy, epID)).
  3. Confirm PolicyProg actually loaded (LoadAndAssign returned nil) and the program type is compatible as a tail-call target.
  4. Ensure ep.GetID() fits the map key type and that the endpoint ID is stable across reloads.
  5. Check kernel >= minimum supported version and program size within verifier complexity limits.

Example fix

// before: stale pinned policy map causes Update to fail silently-looping on reload
// after: unpin and recreate maps when update fails with ENOENT
if err := hostObj.PolicyMap.Update(uint32(ep.GetID()), hostObj.PolicyProg, ebpf.UpdateAny); err != nil {
    if errors.Is(err, os.ErrNotExist) {
        os.RemoveAll(bpf.TCGlobalsPath()) // clear stale pins, agent restart recreates
    }
    return fmt.Errorf("inserting host endpoint policy program: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate pinned map state before reload
func policyMapPinned(epID uint16) error {
    name := bpf.LocalMapName(policymap.MapName, epID)
    path := filepath.Join(bpf.TCGlobalsPath(), name)
    if _, err := os.Stat(path); os.IsNotExist(err) {
        return fmt.Errorf("pinned map %s missing at %s; clear stale pins and restart", name, path)
    }
    return nil
}

Type guard

func isMapUpdateError(err error) bool {
    var eebpf *ebpf.LoadError // or check wrapped errors from ebpf map ops
    _ = eebpf
    return errors.Is(err, unix.EINVAL) || errors.Is(err, unix.ENOENT) ||
        errors.Is(err, unix.ENOSPC)
}

Try / catch

if err := reload(); err != nil {
    if strings.Contains(err.Error(), "inserting host endpoint policy program") {
        if errors.Is(err, unix.ENOENT) {
            // stale pin: recreate maps
            cleanupStalePins(bpf.TCGlobalsPath())
            retryWithBackoff(reload)
            return
        }
        log.Error("policy program insert failed", "detail", errors.Unwrap(err))
    }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/075061867febaa09. Report an issue: GitHub.