gohugoio/hugo · error
resource %T does not implement resource.ReadSeekerCloserReso
Error message
resource %T does not implement resource.ReadSeekerCloserResource
What it means
When Concat lazily opens its inputs, each resource must implement `resource.ReadSeekCloserResource` so its content can be read (and re-read on rebuilds). A resource type that cannot provide a seekable reader — typically a synthetic or wrapper resource that doesn't expose raw content this way — fails this type assertion. The `%T` in the message shows the concrete Go type that lacked the interface.
Source
Thrown at resources/resource_factories/bundler/bundler.go:125
for _, rr := range r {
identity.WalkIdentitiesShallow(rr, func(depth int, id identity.Identity) bool {
terminate = f(id)
return terminate
})
if terminate {
break
}
}
return terminate
},
))
concatr := func() (hugio.ReadSeekCloser, error) {
var rcsources []hugio.ReadSeekCloser
for _, s := range r {
rcr, ok := s.(resource.ReadSeekCloserResource)
if !ok {
return nil, fmt.Errorf("resource %T does not implement resource.ReadSeekerCloserResource", s)
}
rc, err := rcr.ReadSeekCloser()
if err != nil {
// Close the already opened.
for _, rcs := range rcsources {
rcs.Close()
}
return nil, err
}
rcsources = append(rcsources, rc)
}
// Arbitrary JavaScript files require a barrier between them to be safely concatenated together.
// Without this, the last line of one file can affect the first line of the next file and change how both files are interpreted.
if resolvedm.MainType == media.Builtin.JavascriptType.MainType && resolvedm.SubType == media.Builtin.JavascriptType.SubType {
readers := make([]hugio.ReadSeekCloser, 2*len(rcsources)-1)
j := 0View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Inspect what you put in the slice — ensure every element comes from `resources.Get`/`resources.GetMatch`/standard pipes, not from Pages or other non-content values.
- Materialize the resource first (e.g. pipe through `minify`/`fingerprint` or access `.Content`) so a concrete content-backed resource is produced before Concat.
- If it appeared after upgrading Hugo or a module, pin/upgrade the module and report the resource type shown in `%T` upstream.
Defensive patterns
Strategy: type-guard
Type guard
// Go API callers: verify the resource supports seeking before bundling
func canConcat(r resource.Resource) bool {
_, ok := r.(resource.ReadSeekerCloserResource)
return ok
} Prevention
- Pass only file-backed resources (resources.Get, resources.GetMatch) to Concat
- Avoid piping exotic/dynamically-generated resource types into Concat; materialize them first (e.g. resources.FromString) so they're seekable
- When extending Hugo, implement ReadSeekCloser() on custom resource types destined for bundling
When it happens
Trigger: Passing a resource into `resources.Concat` whose concrete type does not implement `ReadSeekCloser()` — e.g. certain lazily-evaluated or error-wrapping resources, resources produced by a transformation that only supports streaming, or objects that are Resources but not content-backed (like some Page-derived values) placed into the slice.
Common situations: Building the Concat slice from mixed template values (accidentally including a Page or params object cast as a resource), using output from a custom/un上游 transformation that broke the interface after a Hugo upgrade, or a plugin/module returning a wrapper resource type.
Related errors
- expected slice of Resource objects, received %T instead
- must provide one or more Resource objects to concat
- failed to copy resources to vendor dir: %w
- no Key set in Resource
- resources.PostProcess cannot be used in a deferred template
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/1fcab7535bfe0fb3.json.
Report an issue: GitHub ↗.