# How the `launch_module` Wrapper Handles Exceptions from Website Modules in holehe

> Learn how holehe's launch_module wrapper catches website module exceptions, logs errors, and ensures uninterrupted scanning for robust security checks.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: internals
- Published: 2026-08-15

---

**The `launch_module` wrapper in holehe catches all exceptions from website modules, logs them as structured error entries, and allows the main scanning loop to continue without interruption.**

The `holehe` repository by **megadose** is an open-source email reconnaissance tool that checks whether an email address is registered on hundreds of websites. Since it runs dozens of concurrent website checks, robust error handling is essential. The `launch_module` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) serves as the protective barrier between individual module failures and the overall scan integrity.

## How `launch_module` Is Invoked

Modules are scheduled concurrently using **Trio's nursery pattern**. In [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) (lines 20–21), each website module is started as a background task:

```python
async with trio.open_nursery() as nursery:
    for website in websites:
        nursery.start_soon(launch_module, website, email, client, out)

```

This schedules every module through the `launch_module` wrapper rather than calling modules directly.

## Exception Handling Implementation

The `launch_module` function is defined in **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) (lines 66–78)**. It wraps module execution in a broad `try/except` block that captures any failure:

```python
async def launch_module(module, email, client, out):
    try:
        await module(email, client, out)
    except Exception:
        name = str(module).split('<function ')[1].split(' ')[0]
        out.append({
            "name": name,
            "domain": data[name],
            "rateLimit": False,
            "error": True,
            "exists": False,
            "emailrecovery": None,
            "phoneNumber": None,
            "others": None
        })

```

### What Happens When a Module Fails

1. **Execution attempt** – The wrapper `await`s the module coroutine (`module(email, client, out)`)
2. **Exception capture** – Any `Exception` subclass triggers the `except` block
3. **Module identification** – The function name is parsed from `str(module)` using string splitting on `'<function '`
4. **Structured logging** – A **uniform result dictionary** is appended to the shared `out` list with:
   - `name`: extracted module identifier (e.g., `"github"`)
   - `domain`: looked up from the static `data` mapping (e.g., `"github.com"`)
   - `rateLimit`: `False` (no rate-limit information available)
   - `error`: `True` (signals this result represents a failure)
   - `exists`: `False` (no positive detection possible)
   - All data fields set to `None`

This guarantees every module produces exactly one result entry, maintaining consistent output structure regardless of success or failure.

## Result Aggregation and Display

After all `launch_module` coroutines complete, results are sorted and rendered. The `error: True` flag triggers visual indicators in terminal output—failures appear with a **red `[!]` tag**, distinguishing them from successful negative results (`[-]`) or positive detections (`[+]`) without disrupting the scan flow.

## Design Benefits

| Aspect | Implementation |
|--------|---------------|
| **Isolation** | One module's failure cannot crash others |
| **Completeness** | Every module contributes to final output |
| **Observability** | Errors are explicitly flagged, not silently dropped |
| **Structured data** | Consistent schema for success and failure cases |

## Summary

- **`launch_module`** in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) is the defensive wrapper protecting holehe's concurrent scan loop
- It **catches all exceptions** from website modules via `except Exception:`
- Failed modules produce **structured error entries** with `error: True`, `exists: False`, and `rateLimit: False`
- The **module name extraction** uses string parsing on `str(module)` to identify the failed checker
- Main scan execution continues **unaffected by individual module crashes**

## Frequently Asked Questions

### What happens if a website module raises an exception in holehe?

The `launch_module` wrapper catches it, constructs a failure result entry with `error: True`, and appends it to the output list. The main scanning loop continues with other modules.

### How does holehe identify which module failed?

It extracts the function name from `str(module)` by splitting on `'<function '` and taking the first token. This parsed name is used to look up the corresponding domain in the static `data` mapping.

### Why does `launch_module` use `except Exception` instead of specific exceptions?

A broad handler ensures **no module can crash the scan**, whether it raises network errors, parsing failures, or unexpected bugs. The trade-off is uniform error reporting without granular failure classification.

### Where is the `launch_module` function defined in the holehe codebase?

It is implemented in **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) at lines 66–78**, invoked from the main async orchestration code around lines 20–21.