Sitelet https://github.com/nodejs/node/issues/51448
Skip to content

node --help | head -n1 throws an error #51448

Description

@jcbhmr

Version

v21.5.0

Platform

Linux codespaces-6c49bb 6.2.0-1018-azure #18~22.04.1-Ubuntu SMP Tue Nov 21 19:25:02 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

node --help | head -n1

How often does it reproduce? Is there a required condition?

always

What is the expected behavior? Why is that the expected behavior?

expected behaviour is what deno and bun do: don't error lol

What do you see instead?

@jcbhmr ➜ /workspaces/my-app (main) $ node --help | head -n1
Usage: node [options] [ script.js ] [arguments]
node:events:497
      throw er; // Unhandled 'error' event
      ^

Error: write EPIPE
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:952:11)
    at Socket._write (node:net:964:8)
    at writeOrBuffer (node:internal/streams/writable:564:12)
    at _write (node:internal/streams/writable:493:10)
    at Writable.write (node:internal/streams/writable:502:10)
    at print (node:internal/main/print_help:216:10)
    at node:internal/main/print_help:233:1
Emitted 'error' event on Socket instance at:
    at emitErrorNT (node:internal/streams/destroy:169:8)
    at emitErrorCloseNT (node:internal/streams/destroy:128:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -32,
  code: 'EPIPE',
  syscall: 'write'
}

Node.js v21.5.0
@jcbhmr ➜ /workspaces/my-app (main) $ echo $?
0

Additional information

No response

Activity

  1. kvakil commented on Jan 14, 2024

    @kvakil
    Contributor

    $? after a pipe is the exit code of the last command in the pipe, which in this case is head -n1. That's why you get 0. If you're using Bash, ${PIPESTATUS[0]} will give you the exit code of node --help which in this case is indeed 1.

    expected behaviour is what deno and bun do: don't error lol

    Could you elaborate a little on why you need this? Is it causing issues for you or just something you noticed out of curiosity?

  2. changed the title [-]`node --help | head -n1` throws an error but still exits with code 0[/-] [+]`node --help | head -n1` throws an error[/+] on Jan 14, 2024
  3. jcbhmr commented on Jan 14, 2024

    @jcbhmr
    ContributorAuthor

    Ohhhh so that's why it exited with code 0! 🤦‍♀️

    Context of how I noticed this: I was trying to trim the massive --help menus of a bunch of different commands like clang, deno, bun, cargo, rustc, node, etc. and node --help | head -n20 failed. 🤷‍♀️

  4. jcbhmr commented on Jan 14, 2024

    @jcbhmr
    ContributorAuthor

    This works:

    node -e 'console.log("a\n".repeat(2000))' | head -n5

    This works:

    node -e 'process.stdout.write("a\n".repeat(2000))' | head -n5

    This is what the node --help printing code looks like:

    function print(stream) {
    const { options, aliases } = require('internal/options');
    // Use 75 % of the available width, and at least 70 characters.
    const width = MathMax(70, (stream.columns || 0) * 0.75);
    const firstColumn = MathFloor(width * 0.4);
    const secondColumn = MathFloor(width * 0.57);
    options.set('-', { helpText: 'script read from stdin ' +
    '(default if no file name is provided, ' +
    'interactive mode if a tty)' });
    options.set('--', { helpText: 'indicate the end of node options' });
    stream.write(
    'Usage: node [options] [ script.js ] [arguments]\n' +
    ' node inspect [options] [ script.js | host:port ] [arguments]\n\n' +
    'Options:\n');
    stream.write(indent(format({
    options, aliases, firstColumn, secondColumn,
    }), 2));
    stream.write('\nEnvironment variables:\n');
    stream.write(format({
    options: envVars, firstColumn, secondColumn,
    }));
    stream.write('\nDocumentation can be found at https://nodejs.org/\n');
    }
    prepareMainThreadExecution();
    markBootstrapComplete();
    print(process.stdout);

    Specifically note the use of multiple .write() calls.

    This FAILS:

    node -e 'for (const i of Array(1000).keys()) process.stdout.write(`${i}\n`)' | head -n5

    This works:

    node -e 'for (const i of Array(1000).keys()) console.log(i)' | head -n5

    What I suggest:

    • use console.log() which appears to already have this swallowing error behaviour
    • OR if that can't happen: change the node --help printing code to use helpText += partN and .write(helpText) with a try block with a catch (error) and if (error?.code !== 'EPIPE') throw error rethrow

    This would:

    1. Not interfere with the useful and expected feature of throwing on closed pipes
    2. Stop the weird error from happening with node --help
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions