gohugoio/hugo · error

expected slice of Resource objects, received %T instead

Error message

expected slice of Resource objects, received %T instead

What it means

Thrown by resources.Concat when the second argument is neither a resource.Resources slice nor a resource.ResourcesConverter. The type switch has only those two cases plus the default that errors, printing the actual Go type via %T.

Solutions

  1. Pass a resource.Resources slice; build one with (slice $r1 $r2) where each element is a Resource.
  2. If you have a single resource, wrap it: (slice $r).
  3. Ensure the slice elements are actual Resource objects returned by resources.Get/Match/etc.
  4. Check the %T in the message to see the concrete type you actually passed.

Example fix

// before (single resource, not a slice):
{{ $out := resources.Concat "app.js" $js }}
// after:
{{ $out := resources.Concat "app.js" (slice $js) }}
Defensive patterns

Strategy: type-guard

Validate before calling

{{ $slice := slice }}
{{ range $r := $candidates }}{{ $slice = $slice | append $r }}{{ end }}
{{ $out := resources.Concat "out.js" $slice }}

Type guard

// Hugo template: ensure each element is a Resource before appending.
{{ $ok := true }}
{{ range $r := $candidates }}{{ if not $r.Params }}{{ $ok = false }}{{ end }}{{ end }}

Prevention

When it happens

Trigger: Calling {{ $r := resources.Concat "out.js" (slice $a $b) }} where the second arg is a single Resource, a []any of resources, a string, or any non-converter value.

Common situations: Passing a single resource instead of a slice, passing a plain Go []any/slice (which is not typed as resource.Resources), or passing the result of a function that returns resource.Resource rather than resource.Resources.

Related errors


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

Appendix: source

Thrown at tpl/resources/resources.go:218

}

// Concat concatenates a slice of Resource objects. These resources must
// (currently) be of the same Media Type.
func (ns *Namespace) Concat(targetPathIn any, r any) (resource.Resource, error) {
	targetPath, err := cast.ToStringE(targetPathIn)
	if err != nil {
		return nil, err
	}

	var rr resource.Resources

	switch v := r.(type) {
	case resource.Resources:
		rr = v
	case resource.ResourcesConverter:
		rr = v.ToResources()
	default:
		return nil, fmt.Errorf("expected slice of Resource objects, received %T instead", r)
	}

	if len(rr) == 0 {
		return nil, errors.New("must provide one or more Resource objects to concat")
	}

	return ns.bundlerClient.Concat(targetPath, rr)
}

// FromString creates a Resource from a string published to the relative target path.
func (ns *Namespace) FromString(targetPathIn, contentIn any) (resource.Resource, error) {
	targetPath, err := cast.ToStringE(targetPathIn)
	if err != nil {
		return nil, err
	}
	content, err := cast.ToStringE(contentIn)
	if err != nil {
		return nil, err

View on GitHub (pinned to 52c9bd7908)