{"id":"7ec1820653cae584","repo":"gohugoio/hugo","slug":"arguments-to-complement-must-be-slices-or-arrays","errorCode":null,"errorMessage":"arguments to complement must be slices or arrays","messagePattern":"arguments to complement must be slices or arrays","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/collections/complement.go","lineNumber":57,"sourceCode":"\n\taset, err := collectIdentities(as...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tv := reflect.ValueOf(universe)\n\tswitch v.Kind() {\n\tcase reflect.Array, reflect.Slice:\n\t\tsl := reflect.MakeSlice(v.Type(), 0, 0)\n\t\tfor i := range v.Len() {\n\t\t\tev, _ := hreflect.Indirect(v.Index(i))\n\t\t\tif _, found := aset[normalize(ev)]; !found {\n\t\t\t\tsl = reflect.Append(sl, ev)\n\t\t\t}\n\t\t}\n\t\treturn sl.Interface(), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"arguments to complement must be slices or arrays\")\n\t}\n}\n","sourceCodeStart":39,"sourceCodeEnd":60,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/collections/complement.go#L39-L60","documentation":"Hugo's `complement` template function returns the elements of the last argument (the \"universe\") that are not present in the earlier arguments. After collecting identities from the earlier arguments, it reflects on the final argument and requires reflect.Kind Array or Slice; any other kind (map, string, Page, int, nil) hits the default case at tpl/collections/complement.go:57 and returns this error.","triggerScenarios":"Calling `{{ complement $a $b }}` or `{{ $x | complement $y }}` in a Hugo template where the last argument (the piped value in the pipe form) is not a slice or array — e.g. a single Page, a map from `dict`, a string, or nil from a failed lookup.","commonSituations":"Piping a single page instead of a page collection (`{{ .Page | complement $x }}`), passing `.Params.something` that is a map or missing (nil), or reversing argument order and putting the exclusion set last while the universe is a scalar. Also happens when a `where` result is nil because the query matched nothing of the expected shape.","solutions":["Ensure the last argument (the piped value when using `|`) is a slice or array, e.g. `.Pages`, `slice ...`, or `.Site.RegularPages`.","Check argument order: `{{ $universe | complement $exclusions }}` — the universe must be the final/piped argument.","Guard against nil/missing collections with `with` or a default: `{{ $c := .Pages | complement (default (slice) $last4) }}`."],"exampleFix":"<!-- before: universe is a single page -->\n{{ $c := .Page | complement $featured }}\n<!-- after: universe is a page collection -->\n{{ $c := .Site.RegularPages | complement $featured }}","handlingStrategy":"type-guard","validationCode":"{{/* ensure every argument is a slice/array before complement */}}\n{{ if and (reflect.IsSlice .setA) (reflect.IsSlice .setB) }}\n  {{ $rest := complement .setA .setB }}\n{{ end }}","typeGuard":"{{ define \"isCollection\" }}{{ or (reflect.IsSlice .) (reflect.IsMap .) }}{{ end }}\n{{/* complement requires slices/arrays specifically: */}}\n{{ $ok := reflect.IsSlice $candidate }}","tryCatchPattern":null,"preventionTips":["Check reflect.IsSlice on each argument before passing it to complement","Watch for single values sneaking in — wrap scalars with (slice $v) if needed","Remember .Params entries may be scalars, not slices, depending on front matter shape","Use printf \"%T\" $v with hdebug/warnf while developing to confirm argument types"],"tags":["hugo","templates","collections","type-mismatch"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}