{"record":{"id":"d1404123ac9a572b","repo":"gohugoio/hugo","slug":"resources-in-concat-must-be-of-the-same-media-type","errorCode":null,"errorMessage":"resources in Concat must be of the same Media Type, got %q and %q","messagePattern":"resources in Concat must be of the same Media Type, got %q and %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/resource_factories/bundler/bundler.go","lineNumber":92,"sourceCode":"\nfunc (r *multiReadSeekCloser) Close() error {\n\tfor _, s := range r.sources {\n\t\ts.Close()\n\t}\n\treturn nil\n}\n\n// Concat concatenates the list of Resource objects.\nfunc (c *Client) Concat(targetPath string, r resource.Resources) (resource.Resource, error) {\n\ttargetPath = path.Clean(targetPath)\n\treturn c.rs.ResourceCache.GetOrCreate(targetPath, func() (resource.Resource, error) {\n\t\tvar resolvedm media.Type\n\n\t\t// The given set of resources must be of the same Media Type.\n\t\t// We may improve on that in the future, but then we need to know more.\n\t\tfor i, rr := range r {\n\t\t\tif i > 0 && rr.MediaType().Type != resolvedm.Type {\n\t\t\t\treturn nil, fmt.Errorf(\"resources in Concat must be of the same Media Type, got %q and %q\", rr.MediaType().Type, resolvedm.Type)\n\t\t\t}\n\t\t\tresolvedm = rr.MediaType()\n\t\t}\n\n\t\tidm := c.rs.Cfg.NewIdentityManager()\n\n\t\t// Re-create on structural changes.\n\t\tidm.AddIdentity(identity.StructuralChangeAdd, identity.StructuralChangeRemove)\n\n\t\t// Add the concatenated resources as dependencies to the composite resource\n\t\t// so that we can track changes to the individual resources.\n\t\tidm.AddIdentityForEach(identity.ForEeachIdentityProviderFunc(\n\t\t\tfunc(f func(identity.Identity) bool) bool {\n\t\t\t\tvar terminate bool\n\t\t\t\tfor _, rr := range r {\n\t\t\t\t\tidentity.WalkIdentitiesShallow(rr, func(depth int, id identity.Identity) bool {\n\t\t\t\t\t\tterminate = f(id)\n\t\t\t\t\t\treturn terminate","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/resource_factories/bundler/bundler.go#L74-L110","documentation":"Returned by `bundler.Client.Concat` (bundler.go:83-95) when two resources in the input list report different `MediaType().Type`. Concat physically joins bytes; mixing media types would corrupt the output (e.g. concatenating CSS into JS). The check at bundler.go:90-93 compares each resource's media type against the first and fails on the first mismatch.","triggerScenarios":"Calling `resources.Concat` (template) / `bundler.Client.Concat` with a list containing, say, a CSS resource and a JS resource, or a JSON and a text resource, or two resources whose media types were configured/assigned differently.","commonSituations":"Bundle pipeline that pulls from `.Resources.Match \"*\"` and accidentally includes a non-JS asset (README, sourcemap, image); media type misconfigured in `mediaTypes` config so two logically same files report different suffixes; partial templates re-used across themes with different default media types.","solutions":["Filter the input list to a single media type before calling Concat (e.g. `resources.Match \"js/**\"`).","Verify each resource's `.MediaType.Type` with a debug print before concat.","Align `mediaTypes` config so equivalent assets share a type.","Split the concat into one call per media type."],"exampleFix":"// template -- before\n{{ $bundle := resources.Concat \"bundle.js\" (resources.Match \"*\") }}\n\n// after\n{{ $bundle := resources.Concat \"bundle.js\" (resources.Match \"js/**\") }}","handlingStrategy":"validation","validationCode":"// In template, verify uniform media type before concat.\n{{ $types := slice }}\n{{ range $r := $input }}{{ $types = $types | append $r.MediaType.Type }}{{ end }}\n{{ if lt (len (uniq $types)) 2 }}{{ $bundle := resources.Concat \"out\" $input }}{{ end }}","typeGuard":null,"tryCatchPattern":"// Guard concat at the Go call site.\nfirst := list[0].MediaType().Type\nfor _, r := range list[1:] {\n\tif r.MediaType().Type != first {\n\t\treturn nil, fmt.Errorf(\"media type mismatch: %s vs %s\", r.MediaType().Type, first)\n\t}\n}\nreturn bundler.Concat(...)","preventionTips":["Use `resources.Match \"<ext>/**\"` to pre-filter to one type.","Log `.MediaType.Type` of each input before concat during dev.","Split multi-type bundles into separate concat calls."],"tags":["resources","bundler","concat","media-type","templates"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}