# Understanding testssl.sh Exit Codes and Error Handling

> Master testssl.sh exit codes! Understand numeric codes from 0 to 255 to effectively handle environmental failures connectivity issues and scan results. Improve your scripts now.

- Repository: [Dirk Wetter/testssl.sh](https://github.com/drwetter/testssl.sh)
- Tags: how-to-guide
- Published: 2026-03-01

---

**testssl.sh uses numeric exit codes from 0 (success) to 255 (fatal Bash error), defined as constants like `ALLOK=0` and `ERR_BASH=255` in the main script, to signal environmental failures, connectivity issues, and scan results to calling processes.**

The [`drwetter/testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/drwetter/testssl.sh) repository provides a single-file Bash solution for SSL/TLS testing that communicates execution status through a structured exit code system. Understanding these **testssl.sh exit codes** is essential for building robust automation, CI/CD pipelines, and error-handling logic around your security scanning workflows.

## testssl.sh Exit Code Reference

In [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh), exit codes are declared as constants between lines 73 and 88. The script reserves the upper range (250–255) for environmental and script-level failures, while lower values indicate specific runtime errors.

- **`ALLOK=0`** (line 88): Successful completion with no errors.
- **`ERR_BASH=255`**: Bash version too old or script not executed with Bash.
- **`ERR_CMDLINE=254`**: Invalid command-line arguments provided.
- **`ERR_FCREATE=253`**: Could not create an output file.
- **`ERR_FNAMEPARSE=252`**: Input file could not be parsed.
- **`ERR_NOSUPPORT=251`**: Requested feature not supported by the current environment.
- **`ERR_OSSLBIN=250`**: Problem locating or executing the OpenSSL binary.
- **`ERR_DNSBIN=249`**: Missing DNS lookup binary.
- **`ERR_OTHERCLIENT=248`**: Other client-related problem.
- **`ERR_DNSLOOKUP=247`**: DNS resolution failure.
- **`ERR_CONNECT=246`**: Network or connectivity problem.
- **`ERR_CLUELESS=245`**: Unexpected internal state.
- **`ERR_RESOURCE=244`**: Needed resource (file, binary, etc.) missing.
- **`ERR_CHILD=242`**: Child process terminated by a signal.

### Why Exit Codes Descend from 255 to 242

Bash treats any non-zero exit status as an error. By placing the most severe, script-wide problems in the 250–255 range and normal error cases below 250, downstream tools can distinguish between *environmental* failures (e.g., missing OpenSSL) and *scan-specific* problems (e.g., unreachable host).

## How testssl.sh Reports Failures

When an error condition is detected, the script calls either `fatal()` (lines 69–81) or `fatal_cmd_line()` (lines 88–100). These functions print a colored diagnostic message to standard error, optionally write to a log file, and terminate execution with `exit $ERR_CODE`. The `fatal()` helper handles general runtime errors, while `fatal_cmd_line()` specifically manages invalid argument errors, often printing usage information before exiting.

## Handling Exit Codes in Automation Scripts

Capture the exit status immediately after invocation using `$?`, then implement conditional logic to handle different failure categories. The following pattern separates environmental errors from connectivity issues:

```bash
#!/usr/bin/env bash
SCAN_OUTPUT=$(mktemp)

# Execute testssl.sh (example host)

./testssl.sh -p -U example.com >"$SCAN_OUTPUT"
RET=$?

# 0 – all fine

if [[ $RET -eq 0 ]]; then
    echo "✅ Scan completed successfully."

# 240–254 – script-level problems (environment, arguments, missing tools)

elif (( RET >= 240 && RET <= 254 )); then
    echo "❗ Critical failure (code $RET). Check the log for Bash version, missing binaries, or wrong arguments."

# 245–246 – connectivity or resource errors

elif (( RET >= 245 && RET <= 246 )); then
    echo "⚠️  Connectivity or resource issue (code $RET). Consider increasing timeout or fixing DNS."

# 242 – child process died (rare, e.g., signal from parallel worker)

elif [[ $RET -eq 242 ]]; then
    echo "⚡ A worker process was killed. Retry the scan or run in serial mode."

# Anything else – unexpected state

else
    echo "❓ Unknown exit code $RET – see testssl.sh documentation."
fi

rm -f "$SCAN_OUTPUT"

```

## Pipeline Integration and Error Propagation

For CI/CD pipelines, use Bash’s strict mode to ensure that [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh) failures immediately halt the pipeline and propagate the correct exit code:

```bash
set -euo pipefail
./testssl.sh -U example.com | tee scan.log

# If testssl.sh exits with any non-zero code, the pipeline aborts immediately

```

The `pipefail` option ensures that errors from [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh) are not masked by the success of `tee`, preserving the original exit code for downstream processing.

## Summary

- **Exit codes range from 0 (success) to 255 (fatal Bash error)**, with specific constants defined in [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh) lines 73–88.
- **Environmental failures** (missing binaries, invalid arguments) use codes 250–255, while **runtime errors** (DNS, connectivity) use 242–249.
- **Internal error handling** relies on `fatal()` (lines 69–81) and `fatal_cmd_line()` (lines 88–100) to report and exit.
- **Capture `$?` immediately** after execution to ensure you read the correct status before running other commands.
- **Use `set -euo pipefail`** in wrapper scripts to propagate testssl.sh failures correctly through pipelines.

## Frequently Asked Questions

### What is the difference between `fatal()` and `fatal_cmd_line()` in testssl.sh?

Both functions terminate the script with an error code, but `fatal()` (lines 69–81) handles general runtime errors, while `fatal_cmd_line()` (lines 88–100) specifically processes invalid command-line argument errors, printing usage information before exiting with `ERR_CMDLINE` (254).

### How can I differentiate between environmental failures and network issues using exit codes?

Environmental and script-level problems (missing binaries, invalid arguments, Bash version issues) occupy the **250–255** range, while network-specific errors use **`ERR_CONNECT` (246)** and **`ERR_DNSLOOKUP` (247)**.

### What should I do if testssl.sh returns exit code 242?

Exit code 242 (`ERR_CHILD`) indicates a child process was terminated by a signal, often occurring during parallel scans. Retry the scan in serial mode or investigate resource limits and signal handling on your system.

### Where are the exit code constants documented in the repository?

The constants are defined in [`testssl.sh`](https://github.com/drwetter/testssl.sh/blob/main/testssl.sh) (lines 73–88), with additional documentation available in [`doc/testssl.1.md`](https://github.com/drwetter/testssl.sh/blob/main/doc/testssl.1.md) (the man page source), [`README.md`](https://github.com/drwetter/testssl.sh/blob/main/README.md), and [`CHANGELOG.md`](https://github.com/drwetter/testssl.sh/blob/main/CHANGELOG.md) which tracks historical changes to exit code semantics.