question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Throwing an error in a command handler can result in truncated stdout/stderr output

See original GitHub issue

Thanks for such a fantastic library. I wanted to help out by dropping a report for a rare bug I saw in case it helps anyone else.

Problem

I was debugging a problem with webpack output getting truncated on failures. This build is wrapped in a yargs command handler. The code looks roughly like this:

async function commandHandler() {
  const compiler = webpack(config);
  const stats = await util.promisify(compiler.run.bind(compiler))();

  if (stats.hasErrors()) {
    console.log(stats.toString());
    throw new Error("Webpack build failed. See error messages above.")
  }
}

This example is adapted slightly from: https://webpack.js.org/api/node/#error-handling

The stats.toString() object here could be quite large, and I was observing output from webpack getting cut off mid-line. It was clear the stdout output wasn’t complete.

Investigation

Making sure stdout was flushed before throwing an error fixed the issue.

console.log(stats.toString());
await new Promise((resolve) => process.stdout.write("", resolve));
throw new Error("Webpack build failed. See error messages above.")

This made me think there was a code path in yargs that called process.exit() after a command handler returns, which would force Node.js to exit before everything on the event queue is processed. Node.js normally waits for all stdout to be written before exiting.

I was able to repro yargs calling process.exit in a debugger. The code path is:

  1. yargs calls yargs.getInternalMethods().getUsageInstance().fail if a command handler returns a rejecting promise:

    https://github.com/yargs/yargs/blob/59a86fb83cfeb8533c6dd446c73cf4166cc455f2/lib/command.ts#L434-L440

  2. This fail handler calls yargs.exit(1) if exitProcess is set. (It is by default.)

    https://github.com/yargs/yargs/blob/59a86fb83cfeb8533c6dd446c73cf4166cc455f2/lib/usage.ts#L70-L71

  3. yargs.exit then calls process.exit

    https://github.com/yargs/yargs/blob/59a86fb83cfeb8533c6dd446c73cf4166cc455f2/lib/yargs-factory.ts#L703-L707

Workarounds

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
bcoecommented, Oct 5, 2022

Do we know if that’s the only reason it’s defaulted to true?

I believe the reasoning was if you’ve triggered an event that should terminate execution, like --help, you don’t want the logic to execute after yargs is invoked.

I think we should leave it defaulting to true.

Would it help if I put up a PR for that?

Can you confirm that the truncation stops if you remove the check for stream.isTTY, if it does, I would happily take a PR for this fix.

1reaction
gluxoncommented, Aug 23, 2022

Thanks @bcoe. Removing the condition might make sense. Would it help if I put up a PR for that?

The other alternative would be to switch the exitProcess(...) default from true to false. This would avoid calling process.exit, which @zaripych also cautioned against. I saw the caveat about that duplicating promise rejection errors though.

  • Do we know if that’s the only reason it’s defaulted to true?
  • If so, could we reasonably address that and switch the default for the next yargs major version bump?
Read more comments on GitHub >

github_iconTop Results From Across the Web

Powershell: Capturing standard out and error with Process ...
I want to start a Java program from PowerShell and get the results printed on the console. I have followed ...
Read more >
Child process | Node.js v19.3.0 Documentation
If exceeded, the child process is terminated and any output is truncated. ... this method will throw an Error that will include the...
Read more >
How do we implement exception handling around Command ...
I have created a simple .NET Core console application with this line to execute the Command try { rootCommand.Invoke(args) } catch { Console ......
Read more >
exceptions - Invoke documentation
Exception subclass representing failure of a command execution. “Failure” may mean the command executed and the shell indicated an unusual result (usually, a ......
Read more >
pytest Documentation - Read the Docs
1.1.4 Assert that a certain exception is raised ... Note: Calling pytest.main() will result in importing your tests and any modules that ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found