cilium/cilium · error

type %s is not a struct

Error message

type %s is not a struct

What it means

check() requires each supplied Go value to be a struct kind, since alignment comparison is defined over struct layouts. If the reflected Kind is anything else (pointer handled per API contract, slice, int, etc.), it errors that the type is not a struct.

Source

Thrown at pkg/alignchecker/alignchecker.go:150

	_memberOffsets(members, offsets, 0, "")
	return offsets
}

func check(name string, toCheck []any, structs map[string]*structInfo, checkOffsets bool) error {
	for _, i := range toCheck {
		c, found := structs[name]
		if !found {
			return fmt.Errorf("could not find C struct %s", name)
		}

		g := reflect.TypeOf(i)
		if g == nil {
			return fmt.Errorf("nil interface passed for type %s", name)
		}

		// Input type must be a struct.
		if g.Kind() != reflect.Struct {
			return fmt.Errorf("type %s is not a struct", name)
		}

		if bs, rs := binary.Size(i), int(g.Size()); bs != rs {
			return fmt.Errorf("type %s's binary.Size (%d) does not equal its unsafe.Sizeof (%d) size (struct with implicit trailing padding?)", g.Name(), bs, rs)
		}

		if c.size != uint32(g.Size()) {
			return fmt.Errorf("%s(%d) size does not match %s(%d)", g, g.Size(),
				name, c.size)
		}

		if !checkOffsets {
			continue
		}

		for field := range g.Fields() {
			fieldName := field.Tag.Get("align")
			// Ignore fields without `align` struct tag

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Supply a Go struct type whose fields (and `align:` tags) mirror the C struct.
  2. Dereference or unwrap wrappers: use the struct value, not a named non-struct type.
  3. Check the test's toCheck literals for wrong types after API changes.

Example fix

// before
toCheck["ct_key4"] = []any{uint32(0)} // not a struct
// after
toCheck["ct_key4"] = []any{CtKey4{}} // Go struct mirror
Defensive patterns

Strategy: type-guard

Type guard

func allStructs(vals []any) bool {
    for _, v := range vals {
        t := reflect.TypeOf(v)
        if t == nil || t.Kind() != reflect.Struct {
            return false
        }
    }
    return true
}
// call before CheckStructAlignments

Try / catch

if err := alignchecker.CheckStructAlignments(obj, toCheck, true); err != nil {
    if strings.Contains(err.Error(), "is not a struct") {
        t.Fatalf("toCheck entries must be Go structs mirroring C structs: %v", err)
    }
    t.Fatal(err)
}

Prevention

When it happens

Trigger: Passing a non-struct Go value (e.g. an integer, slice, or a named type wrapping a non-struct) in toCheck instead of a Go struct mirroring the C struct.

Common situations: Tests written against scalar fields rather than whole structs; refactors replacing a struct with a type alias to a non-struct; confused typedefs where the Go mirror is a basic type.

Related errors


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