Skip to content

fix HelpError handling#36

Merged
boneskull merged 5 commits intomainfrom
fix-helperror
Feb 4, 2026
Merged

fix HelpError handling#36
boneskull merged 5 commits intomainfrom
fix-helperror

Conversation

@boneskull
Copy link
Owner

@boneskull boneskull commented Feb 4, 2026

When a HelpError is thrown (e.g., unknown command, no command specified),
parse() and parseAsync() now catch it and handle gracefully:

  • Error message is printed to stderr
  • Help text is displayed to stderr
  • process.exitCode is set to 1 (no process.exit() call)
  • Returns result with helpShown: true flag

This prevents HelpError from bubbling up to global exception handlers
while still providing useful feedback to the user.

Refactors use of process.exit() and documents exiting behavior.

When a HelpError is thrown (e.g., unknown command, no command specified),
`parse()` and `parseAsync()` now catch it and handle gracefully:

- Error message is printed to stderr
- Help text is displayed to stderr
- `process.exitCode` is set to 1 (no `process.exit()` call)
- Returns result with `helpShown: true` flag

This prevents HelpError from bubbling up to global exception handlers
while still providing useful feedback to the user.

Closes #31
Replace `process.exit()` with `process.exitCode` throughout `parseCore()`:

- `--help` now sets `process.exitCode = 0` and returns `{ helpShown: true }`
- `--version` now sets `process.exitCode = 0` and returns `{ helpShown: true }`
- `--completion-script` now sets appropriate exit code and returns
- `--get-bargs-completions` now sets exit code and returns
- `showNestedCommandHelp()` now returns a result instead of calling exit

This allows the process to terminate naturally, enabling proper cleanup
handlers and making the code more testable and composable.
Copilot AI review requested due to automatic review settings February 4, 2026 03:46
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates bargs to handle HelpError internally (showing help and setting process.exitCode instead of throwing) and removes process.exit()-based early termination paths.

Changes:

  • Catch HelpError in parse() / parseAsync() and return a result containing helpShown: true after emitting help text and setting process.exitCode.
  • Replace process.exit() usage in help/version/completion paths with an earlyExit() result.
  • Update tests to assert help output + process.exitCode rather than expecting rejected promises.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
test/parser-commands.test.ts Updates unknown-command test to assert help output + exitCode and helpShown.
test/bargs.test.ts Adjusts unknown-command and HelpError tests to validate non-throwing behavior and stderr output capture.
src/types.ts Extends CliBuilder.parse() / parseAsync() return types to optionally include helpShown.
src/bargs.ts Implements HelpError catching, removes process.exit() usage, and adds early-exit/help-error handling helpers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Rename `helpShown` to `earlyExit` for clarity (issue #4)
  The flag is now accurately named since it's set for help, version,
  and completion output, not just help display.

- Extract shared test helper `withCapturedStderr()` (issues #2, #3)
  Reduces code duplication in tests that capture stderr and exitCode.

- Handle HelpError in nested command delegation (issue #1)
  `__parseWithParentGlobals()` now catches HelpError so nested builders
  can render their own help instead of bubbling up to the parent.
Restore standard CLI behavior where --help, --version, completion flags,
and error conditions (unknown/missing commands) terminate the process.

Changes:
- `exitProcess()` calls `process.exit()` for help/version/completions
- `handleHelpError()` calls `process.exit(1)` after displaying help
- Remove `earlyExit` flag from return types (no longer needed)
- Update tests to mock `process.exit` instead of checking return values
- Document process termination behavior in README.md

This is what users expect from a CLI - these flags print output and exit.
Copilot AI review requested due to automatic review settings February 4, 2026 04:05
@boneskull boneskull added the bug Something isn't working label Feb 4, 2026
@boneskull boneskull linked an issue Feb 4, 2026 that may be closed by this pull request
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Address review feedback:
- Extract `MockExitError` and `withMockedExit` to `test/helpers/mock-exit.ts`
- Use `Promise.resolve().then(fn)` to handle any thenable, not just Promise
- Consolidate duplicate JSDoc blocks for `handleHelpError`
- Update README example to use sentinel error and `finally` block
@boneskull boneskull changed the title fix HelpError handling and remove process.exit() calls fix HelpError handling Feb 4, 2026
@boneskull boneskull merged commit eee2451 into main Feb 4, 2026
11 checks passed
@boneskull boneskull deleted the fix-helperror branch February 4, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HelpError not being caught properly

1 participant