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 tagView on GitHub (pinned to ac7b90affa)
Solutions
- Supply a Go struct type whose fields (and `align:` tags) mirror the C struct.
- Dereference or unwrap wrappers: use the struct value, not a named non-struct type.
- 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
- Provide full Go struct mirrors of C structs in alignchecker tests, never scalars.
- Mirror every C struct field and add `align:` tags for the fields you assert.
- Re-check Go mirrors after C-side struct changes.
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
- nil interface passed for type %s
- %T is not a pointer to struct
- nil pointer to %T
- %s is not a struct
- recursion on type %s
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/d2d684b415b9bb71.
Report an issue: GitHub.