# Error Handling and Exception Patterns in the nGPT CLI: A Complete Guide

> Explore nGPT CLI error handling patterns. Discover its three-layer architecture, centralized exception handler, and POSIX exit codes for robust command-line applications. Learn to manage errors effectively.

- Repository: [nazDridoy/ngpt](https://github.com/nazdridoy/ngpt)
- Tags: how-to-guide
- Published: 2026-03-07

---

**The nGPT CLI implements a centralized, three-layer error handling architecture that validates arguments before execution, funnels all runtime exceptions through a single handler in [`ngpt/cli/handlers/error_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/error_handler.py), and returns POSIX-compliant exit codes (2 for validation errors, 130 for interrupts, and 1 for unexpected failures).**

The nGPT command-line interface, developed in the `nazdridoy/ngpt` repository, employs sophisticated error handling and exception patterns to ensure robust user feedback and graceful failure recovery. By centralizing exception management and enforcing strict validation at the entry point, the CLI maintains clean separation between user input errors, runtime failures, and system interrupts.

## Centralized Error Handling Architecture

The nGPT CLI follows a **centralized, layered approach** that keeps the core execution flow readable while providing clear, coloured feedback to the user. This architecture divides responsibilities across three distinct layers: argument validation, runtime exception funneling, and graceful termination handling.

### The Three-Layer Validation Strategy

The error handling stack operates through three coordinated layers:

- **Argument Validation Layer**: Detects misuse of CLI flags, missing required arguments, and incompatible option combinations before any heavy processing begins.
- **Exception Funnel Layer**: Catches any exception that bubbles out of the command dispatch and routes it through a single handler that decides whether to show a traceback or a concise error message.
- **Termination Layer**: Handles user-initiated aborts (Ctrl-C) with friendly messaging and appropriate exit codes.

### Exception Funnel in the Entry Point

The entry point in [`ngpt/cli/main.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/main.py) implements the primary exception handling flow using nested try-except blocks:

```python

# ngpt/cli/main.py

try:
    args = validate_args(args)                     # ← validation layer

except ValueError as e:
    handle_validation_error(e)                     # ← validation-error shortcut

try:
    dispatch_mode(client, args, logger=logger)    # → business logic

except KeyboardInterrupt:
    handle_keyboard_interrupt()                    # ← graceful abort

except Exception as e:
    handle_exception(e)                           # ← CLI-wide funnel

```

This structure ensures that validation errors receive immediate attention before API calls or file operations begin, while unexpected runtime failures converge through a single exit path.

## Validation Layer and Argument Checking

The nGPT CLI enforces strict input validation through the `validate_args` function in [`ngpt/cli/args.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/args.py), which raises `ValueError` for any detected misuse, allowing the entry point to catch and route these errors appropriately.

### Pre-execution Validation in `validate_args`

The `validate_args` function performs comprehensive checks before execution:

- **Range validation**: Ensures temperature values fall between 0.0 and 2.0
- **Mutual exclusivity**: Prevents incompatible flag combinations (e.g., `--pipe` used with `--text`)
- **Dependency checking**: Verifies optional dependencies like BeautifulSoup are available when flags like `--web-search` are used
- **Input validation**: Confirms that piped input is actually available when `--pipe` is specified

When any check fails, the function raises `ValueError` with a descriptive message:

```python

# ngpt/cli/args.py

def validate_args(args):
    if args.temperature is not None and not (0.0 <= args.temperature <= 2.0):
        raise ValueError("Temperature must be between 0.0 and 2.0")
    
    if args.pipe and args.text:
        raise ValueError("Cannot use --pipe with --text")
    
    if args.pipe and sys.stdin.isatty():
        raise ValueError("--pipe was specified but no input is piped")
    
    # Additional validation logic...

    return args

```

### Custom Argparse Error Rendering

The CLI overrides the default `argparse.ArgumentParser.error` method within `setup_argument_parser` in [`ngpt/cli/args.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/args.py) to provide coloured error prefixes and usage information instead of plain-text messages:

```python

# ngpt/cli/args.py

def setup_argument_parser():
    parser = argparse.ArgumentParser(...)
    
    def custom_error(message):
        print(f"{Colors.ERROR}error:{Colors.RESET} {message}", file=sys.stderr)
        parser.print_usage(sys.stderr)
        sys.exit(2)
    
    parser.error = custom_error
    return parser

```

This ensures that parsing errors (missing required arguments, unknown flags) receive the same visual treatment as validation errors, maintaining consistency across all error states.

## Runtime Exception Management

Once argument validation passes, the nGPT CLI employs a centralized exception funnel to handle unexpected runtime errors, ensuring consistent user feedback and appropriate exit codes.

### The `handle_exception` Funnel

The `handle_exception` function in [`ngpt/cli/handlers/error_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/error_handler.py) serves as the single catch-all for unexpected exceptions:

```python

# ngpt/cli/handlers/error_handler.py

def handle_exception(e, debug=False):
    if debug:
        import traceback
        traceback.print_exc()
    else:
        print(f"{Colors.ERROR}Error:{Colors.RESET} {e}", file=sys.stderr)
    
    sys.exit(1)

```

This implementation provides two critical features:
- **User-friendly output**: By default, it prints a concise, coloured error message without exposing internal stack traces
- **Debug capability**: When `debug=True`, it prints the full traceback for development or troubleshooting scenarios

### Graceful Keyboard Interrupt Handling

The CLI provides specialized handling for `KeyboardInterrupt` exceptions through `handle_keyboard_interrupt` in the same module:

```python

# ngpt/cli/handlers/error_handler.py

def handle_keyboard_interrupt():
    print(f"\n{Colors.WARNING}Operation cancelled by user.{Colors.RESET} Exiting gracefully.")
    sys.exit(130)

```

This handler:
- Prints a friendly cancellation message using warning colours from [`ngpt/ui/colors.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/ui/colors.py)
- Exits with status code **130**, which follows the POSIX convention for processes terminated by SIGINT (128 + 2)

## Exit Codes and POSIX Compliance

The nGPT CLI adheres to standard Unix exit code conventions, allowing shell scripts and automation tools to reliably detect failure modes:

| Exit Code | Meaning | Trigger |
|-----------|---------|---------|
| **0** | Success | Normal completion |
| **2** | Argument/Validation Error | Invalid flags, missing dependencies, or `argparse` errors |
| **130** | Interrupted | User pressed Ctrl-C (`SIGINT`) |
| **1** | General Error | Unexpected runtime exceptions |

This standardization ensures that CI/CD pipelines can distinguish between usage errors (exit 2) and runtime failures (exit 1), while interactive users receive immediate feedback about cancellation (exit 130).

## Error Handling Examples in Practice

### Triggering a Validation Error

Attempting to set an invalid temperature range demonstrates the validation layer:

```bash

# Temperature must be between 0.0 and 2.0

ngpt --temperature 5.0 "Hello world"

```

**Result:**

```

error: Temperature must be between 0.0 and 2.0

```

This error is raised by `validate_args` in [`ngpt/cli/args.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/args.py) and handled by `handle_validation_error` in [`ngpt/cli/handlers/error_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/error_handler.py), exiting with status code 2.

### Using `--pipe` Without Piped Input

The CLI detects when flags requiring stdin are used inappropriately:

```bash

# Attempting to use --pipe in an interactive terminal

ngpt --pipe "Summarise {}"

```

**Result:**

```

error: --pipe was specified but no input is piped. Use echo 'content' | ngpt --pipe 'prompt with {}'

```

This check occurs within `validate_args` before any API client initialization, preventing unnecessary network overhead for invalid usage patterns.

### Graceful Cancellation During Interactive Sessions

When a user aborts an ongoing operation:

```bash

# Start an interactive session and press Ctrl-C

ngpt -i

```

**Result:**

```

Operation cancelled by user. Exiting gracefully.

```

The `handle_keyboard_interrupt` function ensures the terminal returns to a clean state with exit code 130, following POSIX conventions for interrupted processes.

### Debug Mode for Development

When troubleshooting unexpected failures, the centralized handler supports full traceback output:

```python

# Example internal usage during development

from ngpt.cli.handlers.error_handler import handle_exception

try:
    risky_operation()
except Exception as e:
    handle_exception(e, debug=True)  # Prints full traceback

```

This pattern allows developers to access detailed stack traces while ensuring end-users only see sanitized error messages during normal operation.

## Summary

The nGPT CLI implements a robust, layered error handling strategy that prioritizes user experience and POSIX compliance:

- **Centralized exception funneling** through `handle_exception` in [`ngpt/cli/handlers/error_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/error_handler.py) ensures consistent error presentation and exit codes
- **Pre-execution validation** via `validate_args` in [`ngpt/cli/args.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/args.py) catches configuration errors before resource-intensive operations begin
- **Standardized exit codes** distinguish between validation failures (2), user interrupts (130), and runtime errors (1)
- **Graceful degradation** for keyboard interrupts preserves terminal state and provides clear cancellation feedback
- **Debug mode support** allows full tracebacks during development while protecting end-users from internal stack traces

## Frequently Asked Questions

### How does nGPT handle invalid command-line arguments?

nGPT validates arguments through the `validate_args` function in [`ngpt/cli/args.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/args.py), which raises `ValueError` for any invalid configuration such as temperature values outside the 0.0-2.0 range or incompatible flag combinations. These validation errors are caught in [`ngpt/cli/main.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/main.py) and routed to `handle_validation_error` in [`ngpt/cli/handlers/error_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/error_handler.py), which prints a coloured error message and exits with status code 2.

### What exit codes does nGPT use for different error types?

The CLI follows POSIX conventions: exit code **2** indicates argument validation errors or argparse failures, exit code **130** signals that the user interrupted the process with Ctrl-C (SIGINT), and exit code **1** represents general runtime exceptions or unexpected failures. Successful operations return exit code **0**. This standardization allows shell scripts and automation tools to distinguish between usage errors and system failures.

### Where is the centralized exception handling implemented?

The centralized exception funnel is implemented in [`ngpt/cli/handlers/error_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/error_handler.py) through the `handle_exception` function, which serves as the catch-all for unexpected runtime errors. The entry point in [`ngpt/cli/main.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/main.py) wraps the main dispatch logic in a try-except block that routes all non-validation exceptions to this handler, ensuring consistent error formatting and exit behaviour across the entire application.

### How does nGPT handle keyboard interrupts gracefully?

When a user presses Ctrl-C during operation, the `KeyboardInterrupt` exception is caught in the main execution block of [`ngpt/cli/main.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/main.py) and passed to `handle_keyboard_interrupt` in [`ngpt/cli/handlers/error_handler.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/cli/handlers/error_handler.py). This function prints a friendly cancellation message using warning colours from [`ngpt/ui/colors.py`](https://github.com/nazdridoy/ngpt/blob/main/ngpt/ui/colors.py) and exits with status code 130, following the POSIX convention for SIGINT termination while preserving terminal state.