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 := 0

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. 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.
  2. Materialize the resource first (e.g. pipe through `minify`/`fingerprint` or access `.Content`) so a concrete content-backed resource is produced before Concat.
  3. 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

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


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