Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

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

Abierto Apto para principiantes
#69 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
82/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
javascript, node.js

Línea de trabajo

Comienza con la reproducción enlazada en el issue y, a continuación, inspecciona Gren/Kernel/ChildProcess.js en torno a la construcción del comando y al manejo de la opción de shell. Verifica que NoShell inicie el programa indicado con argumentos separados, mientras que DefaultShell conserve su comportamiento actual, utilizando el programa de Gren proporcionado y la salida como comprobación final.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

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.

Lenguaje dominante
JavaScript
Estrellas
13
Forks
6
Merge medio
4 d 10 h
PR fusionados (30 d)
4

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de gren-lang/node

Todos los issues de gren-lang/node

Issues similares

Más issues de JavaScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.