Hacktoberfest 2026: die Issues, die Maintainer für den Oktober markiert haben – offen und einsteigerfreundlich. Hacktoberfest-Issues durchsuchen

`ChildProcess.spawn` with `NoShell` looks for a program named after the program and its arguments

Offen Anfängerfreundlich
#69 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
2/5
Geschätzter Aufwand
1-3 Stunden
Anfängerfreundlichkeit
82/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
javascript, node.js

Rechercherichtung

Beginne mit der im Issue verlinkten Reproduktion und untersuche dann Gren/Kernel/ChildProcess.js im Bereich der Befehlserstellung und der Behandlung der Shell-Option. Überprüfe, dass NoShell das benannte Programm mit separaten Argumenten startet, während DefaultShell sein bisheriges Verhalten beibehält, und verwende das bereitgestellte Gren-Programm und die Ausgabe als Abschlussprüfung.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

bug

Found against: gren 0.6.6, gren-lang/core 7.4.2, gren-lang/node 6.1.3, node 22
Reproduction: https://github.com/gilramir/gren-bug-reports/tree/main/2026-09-16-childprocess-spawn-noshell-arguments

ChildProcess.spawn with shell = NoShell works for a program with no
arguments and fails for any program given arguments: spawn cp "test" [ "1", "-eq", "1" ] asks node for a program named test 1 -eq 1, which does not
exist. The same call with DefaultShell works. (That the failure crashes the
program instead of reaching onExit is a separate bug, reported separately.)

Reproduction

gren.json dependencies: gren-lang/core 7.4.2, gren-lang/node 6.1.3. Save as src/Main.gren. Build and run with gren make Main --output=app && node app:

module Main exposing (main)

import Bytes exposing (Bytes)
import ChildProcess exposing (Shell(..))
import Init
import Node
import Stream
import Task


rows : Array { label : String, shell : Shell, program : String, arguments : Array String }
rows =
    [ { label = "`DefaultShell`, `test 1 -eq 1`", shell = DefaultShell, program = "test", arguments = [ "1", "-eq", "1" ] }
    , { label = "`NoShell`, `true`", shell = NoShell, program = "true", arguments = [] }
    , { label = "`NoShell`, `test 1 -eq 1`", shell = NoShell, program = "test", arguments = [ "1", "-eq", "1" ] }
    ]

type Msg
    = Spawn Int
    | Exited { row : Int, code : Int }
    | Started


type alias Model =
    { cp : ChildProcess.Permission, stdout : Stream.Writable Bytes }


main : Node.Program Model Msg
main =
    Node.defineProgram { init = init, update = update, subscriptions = \_ -> Sub.none }


init : Node.Environment -> Init.Task { model : Model, command : Cmd Msg }
init env =
    Init.await ChildProcess.initialize <| \cp ->
        Node.startProgram
            { model = { cp = cp, stdout = env.stdout }
            , command = print env.stdout "| spawn | exit code | expected |\n|---|---|---|" (Spawn 0)
            }


print : Stream.Writable Bytes -> String -> Msg -> Cmd Msg
print stdout line next =
    Stream.writeLineAsBytes line stdout |> Task.attempt (\_ -> next)

update msg model =
    when msg is
        Spawn i ->
            { model = model
            , command =
                when Array.get i rows is
                    Just r ->
                        ChildProcess.spawn model.cp r.program r.arguments
                            { shell = r.shell
                            , workingDirectory = ChildProcess.InheritWorkingDirectory
                            , environmentVariables = ChildProcess.InheritEnvironmentVariables
                            , runDuration = ChildProcess.NoLimit
                            , connection = ChildProcess.Ignored (\_ -> Started)
                            , onExit = \code -> Exited { row = i, code = code }
                            }

                    Nothing ->
                        Cmd.none
            }

        Exited { row = i, code } ->
            { model = model
            , command =
                when Array.get i rows is
                    Just r ->
                        print model.stdout ("| " ++ r.label ++ " | " ++ String.fromInt code ++ " | 0 |") (Spawn (i + 1))

                    Nothing ->
                        Cmd.none
            }

        Started ->
            { model = model, command = Cmd.none }

Output:

$ node app
| spawn | exit code | expected |
|---|---|---|
| `DefaultShell`, `test 1 -eq 1` | 0 | 0 |
| `NoShell`, `true` | 0 | 0 |
node:events:497
      throw er; // Unhandled 'error' event
      ^

Error: spawn test 1 -eq 1 ENOENT
    at ChildProcess._handle.onexit (node:internal/child_process:285:19)
    at onErrorNT (node:internal/child_process:483:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:89:21)
Emitted 'error' event on ChildProcess instance at:
    at ChildProcess._handle.onexit (node:internal/child_process:291:12)
    at onErrorNT (node:internal/child_process:483:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:89:21) {
  errno: -2,
  code: 'ENOENT',
  syscall: 'spawn test 1 -eq 1',
  path: 'test 1 -eq 1',
  spawnargs: []
}

Node.js v22.23.2

Cause

Gren/Kernel/ChildProcess.js. Since 6833e85 ("Fix deprecation warning when
spawning child processes") the program and its arguments are joined into one
string whatever the shell option is:

var cmd = [options.__$program].concat(options.__$arguments).join(" ");

var subproc = childProcess.spawn(cmd, {
  // ...
  shell: _ChildProcess_handleShell(shell),

A shell splits that string again; without one, node treats the whole string as
the file to run.

Vorherrschende Sprache
JavaScript
Sterne
13
Forks
6
Ø Merge
4 T. 10 Std.
Gemergte PRs (30 T.)
4

Entwicklungsumgebung

Dieses Projekt bietet weder Dev-Container noch Dockerfile noch Beitragsleitfaden – die Einrichtung liegt bei Ihnen. Beginnen Sie mit der README; die allgemeinen Schritte stehen in unserem Leitfaden für den ersten Beitrag.

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus gren-lang/node

Alle Issues in gren-lang/node

Ähnliche Issues

Weitere Issues zu JavaScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.