gohugoio/hugo · error

arguments to symdiff must be slices or arrays

Error message

arguments to symdiff must be slices or arrays

What it means

`collections.SymDiff` reflects over both arguments and requires each to be a slice or array (tpl/collections/symdiff.go:41-63). Any other kind — string, map, number, nil, a single page — hits the default branch and fails, because symmetric difference is only defined over element collections.

Source

Thrown at tpl/collections/symdiff.go:63

				sliceElemType = sliceType.Elem()
				slice = reflect.MakeSlice(sliceType, 0, 0)
			}

			for i := range v.Len() {
				ev, _ := hreflect.Indirect(v.Index(i))
				key := normalize(ev)

				// Append if the key is not in their intersection.
				if ids1[key] != ids2[key] {
					v, err := convertValue(ev, sliceElemType)
					if err != nil {
						return nil, fmt.Errorf("symdiff: failed to convert value: %w", err)
					}
					slice = reflect.Append(slice, v)
				}
			}
		default:
			return nil, fmt.Errorf("arguments to symdiff must be slices or arrays")
		}
	}

	return slice.Interface(), nil
}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Ensure both arguments are lists — in front matter use `tags: [a, b]` not `tags: a`.
  2. Guard nil/missing params: `{{ with .Params.tags }}{{ . | symdiff $other }}{{ end }}` or `default (slice)`.
  3. Wrap single values in a slice with `slice $v` if you genuinely have one element.
  4. For maps, diff their keys/values explicitly (e.g. via `keys`) — symdiff does not operate on maps.

Example fix

<!-- before: param may be a string or nil -->
{{ $d := .Params.tags | symdiff $other }}
<!-- after -->
{{ $tags := .Params.tags | default (slice) }}
{{ $d := $tags | symdiff $other }}
Defensive patterns

Strategy: type-guard

Type guard

{{ if and (reflect.IsSlice $a) (reflect.IsSlice $b) }}
  {{ $diff := collections.SymDiff $a $b }}
{{ else }}
  {{ errorf "symdiff arguments must be slices, got %T and %T" $a $b }}
{{ end }}

Prevention

When it happens

Trigger: Calling `{{ $x | symdiff $y }}` where either argument is not a slice/array: a map from `dict`, a plain string, an integer, a nil/missing `.Params` value, or a single Page object instead of a page collection.

Common situations: Passing `.Params.tags` when the front matter defines it as a single string instead of a list; passing a `dict` expecting map diffing; a variable that is nil because the param is unset on some pages; forgetting that `first 1 .Pages` returns a slice but `.Site.GetPage` returns a single page.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/6aba6ea83c2934c0.json. Report an issue: GitHub ↗.