gohugoio/hugo · error
expected slice of Resource objects, received %T instead
Error message
expected slice of Resource objects, received %T instead
What it means
`resources.Concat` requires its second argument to be a `resource.Resources` slice (or something convertible via `ResourcesConverter`). Passing a single Resource, a plain slice built with `slice` containing non-resources, or any other type hits the default case of the type switch and fails with the received type.
Source
Thrown at tpl/resources/resources.go:215
}
// 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, errView on GitHub ↗ (pinned to 8a468df065)
Solutions
- Wrap resources in `slice`: `resources.Concat "js/bundle.js" (slice $a $b)`.
- Use `resources.Match "js/*.js"` to get a proper Resources slice directly.
- Ensure every element is a Resource — check `resources.Get` results for nil before appending.
Example fix
<!-- before -->
{{ $bundle := resources.Concat "js/bundle.js" $main }}
<!-- after -->
{{ $bundle := resources.Concat "js/bundle.js" (slice $main) }} Defensive patterns
Strategy: type-guard
Validate before calling
{{ $css := slice (resources.Get "a.css") (resources.Get "b.css") }}{{ $bundle := $css | resources.Concat "bundle.css" }} Type guard
{{ $allResources := true }}{{ range $r := $items }}{{ if not (reflect.IsMap (dict)) }}{{ end }}{{ end }}{{/* practically: ensure every element came from resources.Get / .Resources */}} Try / catch
{{ with try (resources.Concat "bundle.css" $items) }}{{ with .Err }}{{ errorf "concat failed: %s" . }}{{ end }}{{ end }} Prevention
- Pass a slice of Resource objects (from resources.Get, .Resources, etc.), not strings or paths
- Filter out nils: resources.Get returns nil for missing files — check `with` before appending
- Don't mix plain strings with resources in the slice
When it happens
Trigger: `{{ resources.Concat "js/bundle.js" $oneResource }}` passing a single resource instead of a slice; passing a `[]any` that contains strings/paths rather than Resource objects; passing the result of `readDir` or a string glob rather than `resources.Match`.
Common situations: Forgetting to wrap a single resource in `slice`; building the list from file paths instead of `resources.Get` results; mixing nil entries from failed `resources.Get` calls into the slice (making it a generic slice).
Related errors
- type %T not supported in Resource transformations
- must provide one or more Resource objects to concat
- resource %T does not implement resource.ReadSeekerCloserReso
- failed to copy resources to vendor dir: %w
- arguments to complement must be slices or arrays
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/cd2c347f28043650.json.
Report an issue: GitHub ↗.