{"id":"ff078de436b5f988","repo":"gohugoio/hugo","slug":"must-provide-one-or-more-resource-objects-to-conca","errorCode":null,"errorMessage":"must provide one or more Resource objects to concat","messagePattern":"must provide one or more Resource objects to concat","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/resources/resources.go","lineNumber":219,"sourceCode":"func (ns *Namespace) Concat(targetPathIn any, r any) (resource.Resource, error) {\n\ttargetPath, err := cast.ToStringE(targetPathIn)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar rr resource.Resources\n\n\tswitch v := r.(type) {\n\tcase resource.Resources:\n\t\trr = v\n\tcase resource.ResourcesConverter:\n\t\trr = v.ToResources()\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"expected slice of Resource objects, received %T instead\", r)\n\t}\n\n\tif len(rr) == 0 {\n\t\treturn nil, errors.New(\"must provide one or more Resource objects to concat\")\n\t}\n\n\treturn ns.bundlerClient.Concat(targetPath, rr)\n}\n\n// FromString creates a Resource from a string published to the relative target path.\nfunc (ns *Namespace) FromString(targetPathIn, contentIn any) (resource.Resource, error) {\n\ttargetPath, err := cast.ToStringE(targetPathIn)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcontent, err := cast.ToStringE(contentIn)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn ns.createClient.FromString(targetPath, content)\n}","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/tpl/resources/resources.go#L201-L237","documentation":"After type-checking, `resources.Concat` verifies the Resources slice is non-empty; concatenating zero resources would produce nothing, so Hugo fails fast instead of emitting an empty output file. This is Hugo's fail-fast guard against silently publishing an empty bundle.","triggerScenarios":"`resources.Concat $target (resources.Match \"js/*.js\")` when the glob matches no files in /assets; building the slice conditionally and every condition being false; filtering a Resources slice down to empty with `where`.","commonSituations":"Assets placed in /static instead of /assets (Match only searches the assets filesystem); a glob pattern that doesn't cross directories (`*.js` doesn't match `js/app.js` — use `js/*.js` or `**.js`); theme expecting asset files the site doesn't provide; environment-conditional bundles.","solutions":["Confirm the files live under /assets (or a configured assetDir), not /static.","Fix the glob: `*` doesn't match `/`; use `js/*.js` or `**.js`.","Guard the concat: `{{ with resources.Match \"js/*.js\" }}{{ $b := resources.Concat \"js/bundle.js\" . }}{{ end }}`."],"exampleFix":"<!-- before -->\n{{ $b := resources.Concat \"bundle.js\" (resources.Match \"*.js\") }}\n<!-- after -->\n{{ with resources.Match \"js/**.js\" }}\n  {{ $b := resources.Concat \"bundle.js\" . }}\n{{ end }}","handlingStrategy":"validation","validationCode":"{{ $items := slice }}{{ with resources.Get \"a.css\" }}{{ $items = $items | append . }}{{ end }}{{ if $items }}{{ $bundle := $items | resources.Concat \"bundle.css\" }}{{ end }}","typeGuard":"{{ $nonEmpty := gt (len $items) 0 }}","tryCatchPattern":"{{ with try (resources.Concat \"bundle.css\" $items) }}{{ with .Err }}{{ warnf \"nothing to concat: %s\" . }}{{ end }}{{ end }}","preventionTips":["Check the slice is non-empty before calling Concat — conditional appends can leave it empty","Fail fast with errorf if expected assets are missing rather than concatenating an empty set"],"tags":["hugo","resources","concat","empty-input"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}