gohugoio/hugo · error

cannot append slice of

Error message

cannot append slice of %s to slice of %s

What it means

Returned when the destination slice is a slice-of-slices (tot.Kind()==Slice) and an element being appended does not match the inner element type. Append requires homogeneous slice-of-slice contents; mismatched inner types are rejected rather than silently widening.

Solutions

  1. Inspect both type names printed in the message (from-type, to-type) and align them.
  2. Convert the source slice elements to match the destination inner element type before appending.
  3. If heterogeneous data is intentional, use `[]any` as the inner type on both sides.

Example fix

// before
dst := [][]string{{"a"}}
collections.Append(dst, []int{1})
// after
dst := [][]any{{"a"}}
collections.Append(dst, []any{1})
Defensive patterns

Strategy: type-guard

Validate before calling

func sameInnerElem(dst any, src any) bool {
  d := reflect.TypeOf(dst); s := reflect.TypeOf(src)
  if d == nil || s == nil { return false }
  if d.Kind() != reflect.Slice || d.Elem().Kind() != reflect.Slice { return false }
  if s.Kind() == reflect.Slice { s = s.Elem() }
  return d.Elem().Elem() == s
}

Type guard

func canAppendNested(dst, src any) bool { return sameInnerElem(dst, src) }

Prevention

When it happens

Trigger: Calling Append on a `[][]string` with a `[]int`, or on `[][]any` with a non-slice scalar that fails the inner-type check at append.go:57-58.

Common situations: Template code that mixes heterogeneous list types into a nested slice (e.g. appending a list of tags to a list-of-list-of-sections). Config-driven pipelines that build matrix dimensions from mismatched frontmatter fields.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/dbec3348886de1bf. Report an issue: GitHub.

Appendix: source

Thrown at common/collections/append.go:58

			tov = c
		}

		if tov.Kind() != reflect.Slice {
			return nil, fmt.Errorf("expected a slice, got %T", to)
		}

		tot = tov.Type().Elem()
		if tot.Kind() == reflect.Slice {
			totvt := tot.Elem()
			fromvs := make([]reflect.Value, len(from))
			for i, f := range from {
				fromv := reflect.ValueOf(f)
				fromt := fromv.Type()
				if fromt.Kind() == reflect.Slice {
					fromt = fromt.Elem()
				}
				if totvt != fromt {
					return nil, fmt.Errorf("cannot append slice of %s to slice of %s", fromt, totvt)
				} else {
					fromvs[i] = fromv
				}
			}
			return reflect.Append(tov, fromvs...).Interface(), nil

		}

		toIsNil = tov.Len() == 0

		if len(from) == 1 {
			fromv := reflect.ValueOf(from[0])
			if !fromv.IsValid() {
				// from[0] is nil
				return appendToInterfaceSliceFromValues(tov, fromv)
			}
			fromt := fromv.Type()
			if fromt.Kind() == reflect.Slice {

View on GitHub (pinned to 52c9bd7908)