gohugoio/hugo · error
resources in Concat must be of the same Media Type, got %q a
Error message
resources in Concat must be of the same Media Type, got %q and %q
What it means
`resources.Concat` requires every resource in the slice to share the same media type (e.g. all `text/css` or all `text/javascript`), because the concatenated output resource must carry a single media type and Hugo cannot safely infer one from a mixed set. The check compares each resource's `MediaType().Type` against the first one and fails on the first mismatch.
Source
Thrown at resources/resource_factories/bundler/bundler.go:92
func (r *multiReadSeekCloser) Close() error {
for _, s := range r.sources {
s.Close()
}
return nil
}
// Concat concatenates the list of Resource objects.
func (c *Client) Concat(targetPath string, r resource.Resources) (resource.Resource, error) {
targetPath = path.Clean(targetPath)
return c.rs.ResourceCache.GetOrCreate(targetPath, func() (resource.Resource, error) {
var resolvedm media.Type
// The given set of resources must be of the same Media Type.
// We may improve on that in the future, but then we need to know more.
for i, rr := range r {
if i > 0 && rr.MediaType().Type != resolvedm.Type {
return nil, fmt.Errorf("resources in Concat must be of the same Media Type, got %q and %q", rr.MediaType().Type, resolvedm.Type)
}
resolvedm = rr.MediaType()
}
idm := c.rs.Cfg.NewIdentityManager()
// Re-create on structural changes.
idm.AddIdentity(identity.StructuralChangeAdd, identity.StructuralChangeRemove)
// Add the concatenated resources as dependencies to the composite resource
// so that we can track changes to the individual resources.
idm.AddIdentityForEach(identity.ForEeachIdentityProviderFunc(
func(f func(identity.Identity) bool) bool {
var terminate bool
for _, rr := range r {
identity.WalkIdentitiesShallow(rr, func(depth int, id identity.Identity) bool {
terminate = f(id)
return terminateView on GitHub ↗ (pinned to 8a468df065)
Solutions
- Transform all resources to the target type before Concat, e.g. pipe SCSS through `css.Sass` (and JS through `js.Build`) first.
- Tighten the glob so only one file type is matched, e.g. `resources.Match "css/*.css"` instead of a wildcard over mixed assets.
- Print each resource's `.MediaType` in the template to find the odd one out, then fix its pipeline or the `mediaTypes` config.
Example fix
{{/* before */}}
{{ $css := slice (resources.Get "main.scss") (resources.Get "extra.css") | resources.Concat "bundle.css" }}
{{/* after */}}
{{ $main := resources.Get "main.scss" | css.Sass }}
{{ $css := slice $main (resources.Get "extra.css") | resources.Concat "bundle.css" }} Defensive patterns
Strategy: validation
Validate before calling
{{/* pre-check media types before Concat in a template */}}
{{ $files := slice (resources.Get "a.js") (resources.Get "b.js") }}
{{ $mt := (index $files 0).MediaType.Type }}
{{ range $files }}
{{ if ne .MediaType.Type $mt }}
{{ errorf "Concat mix: %s vs %s (%s)" $mt .MediaType.Type .Name }}
{{ end }}
{{ end }}
{{ $bundle := $files | resources.Concat "bundle.js" }} Prevention
- Only Concat resources with identical media types — group JS with JS, CSS with CSS
- Use consistent file extensions; a .js vs .mjs mismatch can yield different media types
- Run minify/toCSS transforms before Concat so all inputs converge to one type
- Use resources.Match with a single-extension glob (e.g. "js/*.js") to build the concat slice
When it happens
Trigger: Calling `resources.Concat $target $slice` in a template where the slice mixes types — e.g. a `.css` file with a `.js` file, or a `.scss` resource that was not piped through `css.Sass` first (media type `text/x-scss` vs `text/css`), or minified vs source assets whose extensions map to different configured media types.
Common situations: Forgetting to run `toCSS`/`css.Sass` on SCSS resources before concatenating them with plain CSS; globbing too broadly (`resources.Match "assets/**"`) and picking up source maps or unrelated files; custom `mediaTypes` config mapping an extension to an unexpected type; template refactors that reorder pipes so Concat runs before the transform.
Related errors
- MIME %q not supported
- no Resource provided in transformation
- MIME %q not supported
- failed to parse Resource %q as Template:: %w
- error building site: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/d1404123ac9a572b.json.
Report an issue: GitHub ↗.