{"id":"3832fc16e4f4308e","repo":"gohugoio/hugo","slug":"invalid-loader-q","errorCode":null,"errorMessage":"invalid loader: %q","messagePattern":"invalid loader: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/esbuild/options.go","lineNumber":315,"sourceCode":"\t\ttarget = api.ESNext\n\t}\n\n\tvar loaders map[string]api.Loader\n\tif opts.IsCSS {\n\t\tloaders = make(map[string]api.Loader)\n\t\t// Add default CSS file loaders.\n\t\t// May be overridden by opts.Loaders.\n\t\tmaps.Copy(loaders, extensionToLoaderMapCSS)\n\t}\n\tif opts.Loaders != nil {\n\t\tif loaders == nil {\n\t\t\tloaders = make(map[string]api.Loader)\n\t\t}\n\n\t\tfor k, v := range opts.Loaders {\n\t\t\tloader, found := nameLoader[v]\n\t\t\tif !found {\n\t\t\t\terr = fmt.Errorf(\"invalid loader: %q\", v)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tloaders[k] = loader\n\t\t}\n\t}\n\n\tmediaType := opts.MediaType\n\tif mediaType.IsZero() {\n\t\tmediaType = media.Builtin.JavascriptType\n\t}\n\n\tvar loader api.Loader\n\tswitch mediaType.SubType {\n\tcase media.Builtin.JavascriptType.SubType:\n\t\tloader = api.LoaderJS\n\tcase media.Builtin.TypeScriptType.SubType:\n\t\tloader = api.LoaderTS\n\tcase media.Builtin.TSXType.SubType:","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/internal/js/esbuild/options.go#L297-L333","documentation":"The `loaders` option of js.Build maps file extensions to esbuild loaders (e.g. \".png\" → \"dataurl\"). Hugo translates each configured loader name through its nameLoader table into an esbuild api.Loader; a name not in that table aborts option decoding, since esbuild would otherwise misinterpret the files.","triggerScenarios":"`js.Build` with a `loaders` dict whose value isn't a recognized loader name, e.g. `dict \"loaders\" (dict \".svg\" \"url\")` — \"url\" isn't in Hugo's loader map. Valid names include js, jsx, ts, tsx, css, json, text, base64, dataurl, file, binary, copy, empty.","commonSituations":"Using webpack loader names (\"url\", \"raw\") instead of esbuild's (\"dataurl\", \"text\"); typos like \"data-url\"; expecting a loader added in a newer esbuild than the one vendored in the installed Hugo version.","solutions":["Use a loader name esbuild supports: replace \"url\" with \"dataurl\", \"raw\" with \"text\", etc.","Check spelling against esbuild's content-types docs (no hyphens: \"dataurl\", not \"data-url\").","If the loader is newer than your Hugo's bundled esbuild, upgrade Hugo."],"exampleFix":"{{/* before */}}\n{{ $opts := dict \"loaders\" (dict \".svg\" \"url\") }}\n{{/* after */}}\n{{ $opts := dict \"loaders\" (dict \".svg\" \"dataurl\") }}","handlingStrategy":"validation","validationCode":"validLoaders := map[string]bool{\"none\":true,\"base64\":true,\"binary\":true,\"copy\":true,\"css\":true,\"dataurl\":true,\"empty\":true,\"file\":true,\"js\":true,\"json\":true,\"jsx\":true,\"text\":true,\"ts\":true,\"tsx\":true}\nfor ext, l := range opts.Loaders {\n    if !validLoaders[l] {\n        return fmt.Errorf(\"invalid loader %q for %s\", l, ext)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only use esbuild loader names (js, jsx, ts, tsx, json, css, text, base64, dataurl, file, ...)","Loader names are lowercase — \"TSX\" is invalid","Validate any user-supplied loader map in templates before calling js.Build"],"tags":["hugo","js-build","esbuild","loaders","config"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}