{"id":"5fefb45cd4dd3988","repo":"gohugoio/hugo","slug":"invalid-engine-version-q","errorCode":null,"errorMessage":"invalid engine version: %q","messagePattern":"invalid engine version: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/esbuild/options.go","lineNumber":284,"sourceCode":"func (opts *Options) compile() (err error) {\n\tvar target api.Target\n\tfor _, value := range opts.Target {\n\t\tif v, found := nameTarget[value]; found {\n\t\t\tif v > target {\n\t\t\t\ttarget = v\n\t\t\t}\n\t\t}\n\t}\n\n\tvar engines []api.Engine\n\nOUTER:\n\tfor _, value := range opts.Target {\n\t\tfor _, engine := range engineKeysSorted {\n\t\t\tif strings.HasPrefix(value, engine) {\n\t\t\t\tversion := value[len(engine):]\n\t\t\t\tif version == \"\" {\n\t\t\t\t\treturn fmt.Errorf(\"invalid engine version: %q\", value)\n\t\t\t\t}\n\t\t\t\tengines = append(engines, api.Engine{Name: engineName[engine], Version: version})\n\t\t\t\tcontinue OUTER\n\t\t\t}\n\t\t}\n\t}\n\n\tif target == 0 && len(engines) == 0 && len(opts.Target) > 0 {\n\t\treturn fmt.Errorf(\"unsupported target: %v\", opts.Target)\n\t}\n\n\tif target == 0 {\n\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)","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/gohugoio/hugo/blob/8a468df065a75c1c7cf9f6850f32148746590ea5/internal/js/esbuild/options.go#L266-L302","documentation":"js.Build's `target` option accepts either ES versions (es2018, esnext, …) or engine targets like chrome58, node12, safari11. When a target string starts with a known engine name, Hugo splits off the version suffix; an empty suffix (just \"chrome\" or \"node\") is invalid because esbuild requires an engine version.","triggerScenarios":"Passing a target that matches an engine prefix with nothing after it, e.g. `dict \"target\" \"node\"` or `\"target\" (slice \"chrome\")` — the version substring after the engine name is empty, so decoding options fails.","commonSituations":"Writing `target = \"node\"` expecting a generic Node target; copying browserslist-style names without versions; templating the version number and having the variable render empty.","solutions":["Append a version to the engine name, e.g. \"node18\", \"chrome90\", \"safari15\".","If you don't care about a specific engine, use an ES version instead: \"es2018\" or \"esnext\".","If the version is templated, ensure the variable is non-empty before building the target string."],"exampleFix":"{{/* before */}}\n{{ $opts := dict \"target\" \"node\" }}\n{{/* after */}}\n{{ $opts := dict \"target\" \"node18\" }}","handlingStrategy":"validation","validationCode":"var reEngineVer = regexp.MustCompile(`^\\d+(\\.\\d+){0,2}$`)\nif !reEngineVer.MatchString(ver) {\n    return fmt.Errorf(\"bad engine version %q\", ver)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass plain semver-ish versions to js.Build target engines (e.g. \"chrome100\"), no \"v\" prefix or ranges","Validate build options coming from site params before invoking js.Build","Pin the option in config rather than computing it dynamically"],"tags":["hugo","js-build","esbuild","config"],"analyzedSha":"8a468df065a75c1c7cf9f6850f32148746590ea5","analyzedAt":"2026-07-31T21:23:07.045Z","schemaVersion":2}