gohugoio/hugo · error
arguments to complement must be slices or arrays
Error message
arguments to complement must be slices or arrays
What it means
Thrown by Namespace.Complement when the LAST argument (the 'universe' set) is neither an array nor a slice. Complement returns elements in the universe not present in the preceding argument sets; the universe must be a positional iterable. Note the preceding args are validated separately by collectIdentities, so this specific error targets only the final argument.
Solutions
- Ensure the last argument is a slice/array: `{{ complement $exclude $allPages }}`.
- Check pipe direction — Complement's last positional arg is the universe, so `{{ $all | complement $exclude }}` puts $all last correctly.
- Wrap a single value: `{{ complement $exclude (slice $x) }}`.
- Log the type of the universe variable before calling to diagnose.
Example fix
// before
{{ complement $exclude "notalist" }}
// after
{{ complement $exclude $allPages }} Defensive patterns
Strategy: type-guard
Validate before calling
func complementLastIsSlice(args ...any) error {
if len(args) < 2 { return errors.New("need >=2 args") }
u := args[len(args)-1]
k := reflect.ValueOf(u).Kind()
if k != reflect.Slice && k != reflect.Array {
return fmt.Errorf("universe must be slice/array, got %T", u)
}
return nil
} Type guard
func isSliceOrArray(v any) bool {
if v == nil { return false }
k := reflect.ValueOf(v).Kind()
return k == reflect.Slice || k == reflect.Array
} Prevention
- Remember Complement's LAST argument is the universe — keep it a slice/array.
- Check pipe direction so the universe lands in the last slot.
- Wrap a single value in a slice before complement.
- Log operand types when debugging complement failures.
When it happens
Trigger: Calling `{{ complement $set1 "string" }}`, `{{ complement $set1 $someMap }}`, or `{{ .Pages | complement $lastFour }}` where `.Pages` resolved to a non-slice. The switch in Complement inspects reflect.Kind of `universe`; non Slice/Array falls to the default branch.
Common situations: Pipe order confusion (the universe ends up being a single page or string), front matter feeding a scalar into the universe slot, or a variable that was expected to be `.Pages` but is nil/typed differently after a refactor.
Related errors
- arguments must be slices or arrays
- arguments to symdiff must be slices or arrays
- can't index item of type
- can't iterate over %T
- cannot index slice/array with type
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/7ec1820653cae584.
Report an issue: GitHub.
Appendix: source
Thrown at tpl/collections/complement.go:57
aset, err := collectIdentities(as...)
if err != nil {
return nil, err
}
v := reflect.ValueOf(universe)
switch v.Kind() {
case reflect.Array, reflect.Slice:
sl := reflect.MakeSlice(v.Type(), 0, 0)
for i := range v.Len() {
ev, _ := hreflect.Indirect(v.Index(i))
if _, found := aset[normalize(ev)]; !found {
sl = reflect.Append(sl, ev)
}
}
return sl.Interface(), nil
default:
return nil, fmt.Errorf("arguments to complement must be slices or arrays")
}
}
View on GitHub (pinned to 52c9bd7908)