{"record":{"id":"c12f91ba58616ccd","repo":"gohugoio/hugo","slug":"binary-q-is-not-a-node-js-script","errorCode":null,"errorMessage":"binary %q is not a Node.js script","messagePattern":"binary %q is not a Node\\.js script","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/hexec/exec.go","lineNumber":217,"sourceCode":"\t\t\tresolvedBin = p\n\t\t\tloc = binaryLocationNodeModules\n\t\t} else if p, err := exec.LookPath(name); err == nil {\n\t\t\tresolvedBin = p\n\t\t\tloc = binaryLocationPath\n\t\t} else {\n\t\t\treturn nil, &NotFoundError{name: name, method: \"in PATH\"}\n\t\t}\n\n\t\tscriptPath := resolveNodeBin(resolvedBin)\n\n\t\te.infol.WithFields(logg.Fields{\n\t\t\tlogg.Field{Name: \"location\", Value: loc},\n\t\t\tlogg.Field{Name: \"bin\", Value: resolvedBin},\n\t\t\tlogg.Field{Name: \"script\", Value: scriptPath},\n\t\t}).Logf(\"resolve %q\", name)\n\n\t\tif scriptPath == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"binary %q is not a Node.js script\", name)\n\t\t}\n\n\t\treturn func(arg2 ...any) (Runner, error) {\n\t\t\treturn e.newNode(name, scriptPath, arg2...)\n\t\t}, nil\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn newRunner(arg...)\n}\n\n// newNode runs a Node.js script via \"node [--permission <flags>] <scriptPath> <args>\".\nfunc (e *Exec) newNode(name, scriptPath string, arg ...any) (Runner, error) {\n\tvar allArgs []any\n\tfor _, pa := range e.nodePermissionArgs(name, scriptPath) {\n\t\tallArgs = append(allArgs, pa)","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/common/hexec/exec.go#L199-L235","documentation":"Returned by Exec.Npx when a binary found in node_modules/.bin or PATH cannot be resolved to a Node.js script. resolveNodeBin returns '' for files that are not a symlink to a .js/.mjs/.cjs file, lack a `node` shebang, and have no extractable JS entry point from an npm wrapper script. Npx always invokes Node, so an unresolvable entry point is fatal.","triggerScenarios":"Calling Exec.Npx(name,...) where `name` resolves to a native binary, a corrupt npm wrapper, a Windows .cmd whose entry-point regex does not match, or a symlink whose target is not a JS file.","commonSituations":"Hugo running PostCSS/Tailwind/Babel via the js.Bundler pipe or hugo.Stats after a broken `npm install`, a globally installed native tool shadowing the node_modules shim, or a package whose bin field points to a non-JS launcher.","solutions":["Reinstall Node deps cleanly: remove node_modules and package-lock, then `npm install`.","Verify the binary is a Node script: `head -1 node_modules/.bin/<name>` should show a node shebang, or the .cmd wrapper should reference a .js entry.","If a native binary is intended, do not route it through Npx; use Exec.New instead.","Upgrade the offending npm package; older wrappers (e.g. postcss-cli 7) had different layouts."],"exampleFix":"// before\nrunner, err := exec.Npx(\"my-native-tool\", args...)\n// after\nrunner, err := exec.New(\"my-native-tool\", args...)","handlingStrategy":"validation","validationCode":"func isNodeScriptBin(path string) bool {\n  if p, err := filepath.EvalSymlinks(path); err == nil {\n    if strings.HasSuffix(p, \".js\") || strings.HasSuffix(p, \".mjs\") || strings.HasSuffix(p, \".cjs\") { return true }\n  }\n  f, err := os.Open(path); if err != nil { return false }; defer f.Close()\n  b := bufio.NewReader(f); l, _ := b.ReadString('\\n')\n  return strings.HasPrefix(l, \"#!\") && strings.Contains(l, \"node\")\n}","typeGuard":null,"tryCatchPattern":"r, err := exec.Npx(name, args...)\nif err != nil {\n  if strings.Contains(err.Error(), \"is not a Node.js script\") {\n    // fall back to Exec.New for native binaries, or surface install instructions\n  }\n  return err\n}","preventionTips":["Pin npm packages to versions known to ship JS wrappers.","Verify `head -1 node_modules/.bin/<name>` after install.","Separate native-binary tools from Npx-routed Node tools."],"tags":["hexec","npx","node","npm","binary"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}