cilium/cilium · error

converting struct to map: %w

Error message

converting struct to map: %w

What it means

applyConstants converts the Go config struct passed in CollectionOptions.Constants into a map of field name -> value via config.Map, which relies on struct tags and reflection. This error wraps any failure of that conversion - invalid field types, unsupported kinds, or malformed config tags in the struct. It fires before any BPF variable is touched, so the problem is in the Go config object, not the ELF.

Source

Thrown at pkg/bpf/constants.go:30

	"reflect"
	"strings"

	"github.com/cilium/ebpf"

	"github.com/cilium/cilium/pkg/datapath/config"
	"github.com/cilium/cilium/pkg/datapath/config/types"
)

// applyConstants sets the values of BPF C runtime configurables defined using
// the DECLARE_CONFIG macro.
func applyConstants(spec *ebpf.CollectionSpec, obj any) error {
	if obj == nil {
		return nil
	}

	constants, err := config.Map(obj)
	if err != nil {
		return fmt.Errorf("converting struct to map: %w", err)
	}

	for name, value := range constants {
		constName := types.ConstantPrefix + name

		v, ok := spec.Variables[constName]
		if !ok {
			return fmt.Errorf("can't set non-existent Variable %s", name)
		}

		if v.SectionName != types.ConstantSection {
			return fmt.Errorf("can only set Cilium config variables in section %s (got %s:%s), ", types.ConstantSection, v.SectionName, name)
		}

		if err := v.Set(value); err != nil {
			return fmt.Errorf("setting Variable %s: %w", name, err)
		}
	}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Check the wrapped %w error to find the offending struct field and fix its Go type or config tag
  2. Restrict Constants struct fields to types supported by pkg/datapath/config (ints, bools, strings, etc.)
  3. Pass a nil/simple config if the object doesn't need constants, or update config.Map to support the new type

Example fix

// before
 type Config struct {
     Routes map[string]string `config:"routes"` // unsupported kind
 }

// after
 type Config struct {
     RouteCount uint32 `config:"route_count"`
 }
Defensive patterns

Strategy: validation

Validate before calling

if opts.Constants != nil {
    if _, err := config.Map(opts.Constants); err != nil {
        return fmt.Errorf("invalid config struct: %w", err)
    }
}

Type guard

func constantsConvertible(obj any) bool {
    if obj == nil {
        return true
    }
    _, err := config.Map(obj)
    return err == nil
}

Try / catch

if err := LoadAndAssign(logger, &obj, spec, opts); err != nil {
    if strings.Contains(err.Error(), "converting struct to map") {
        return fmt.Errorf("config struct has unsupported fields; check types and config tags: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: LoadCollection/LoadAndAssign called with opts.Constants containing a struct whose fields have types config.Map cannot marshal (e.g. unsupported nested/complex kinds) or whose config struct tags are invalid.

Common situations: Adding a new field to a datapath config struct with an unsupported Go type; typos or wrong tags on config fields; passing a type not registered with the config conversion machinery.

Related errors


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