What Happens When a Module Throws an Exception During Execution in Holehe
When a module throws an exception during execution in Holehe, the launch_module coroutine in holehe/core.py catches the error, appends a failure record with "error": True to the output list, and allows the remaining modules to continue running without crashing the entire scan.
Holehe is a popular open-source email OSINT tool that checks for account existence across hundreds of online services. When a module throws an exception during execution in Holehe—whether due to network timeouts, unexpected HTML structures, or API changes—the tool implements a fail-soft strategy that prevents total execution failure while maintaining a consistent data schema for reporting.
Exception Handling in the Core Execution Loop
The orchestration logic resides in holehe/core.py, specifically within the launch_module coroutine. This function wraps each module call inside a broad try … except Exception block to ensure robust error isolation between individual service checks.
The launch_module Coroutine
Between lines 66–78 of holehe/core.py, the execution flow protects against unhandled exceptions:
async def launch_module(module, email, client, out):
# ... setup code ...
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,
})
If the awaited module call raises any exception, the code extracts the module name from its string representation, constructs a standardized error dictionary using the data mapping for domain resolution, and appends it to the shared out list.
Error Result Structure
When a module fails, Holehe records a placeholder result with specific boolean flags that downstream functions interpret. The appended dictionary contains:
"error": True— Indicates the module raised an exception during execution."rateLimit": False— No rate-limit information is available when the module crashes."exists": False— No positive account-existence evidence can be reported."emailrecovery","phoneNumber","others"— Set toNonebecause the exception prevented data extraction.
This structure ensures that the final output maintains consistent schema even for failed checks, allowing aggregation and sorting logic to proceed without null pointer errors.
Visual Indicators in Terminal Output
The error status propagates to the user interface through the print_result function, also located in holehe/core.py. Lines 26–31 check the results["error"] flag and render a red [!] marker next to the service name.
This visual feedback immediately alerts analysts that a particular module failed—distinguishing execution errors from negative account existence results—without interrupting the scan progress of remaining modules.
Practical Example: Simulating a Module Failure
You can observe this behavior by programmatically triggering the exception handler. Below is a minimal reproduction that demonstrates how Holehe processes a faulty module:
import asyncio
import httpx
from holehe.core import launch_module
async def faulty_module(email, client, out):
# Simulate a runtime error (e.g., network timeout or parsing failure)
raise RuntimeError("simulated module failure")
async def demo():
results = []
async with httpx.AsyncClient() as client:
await launch_module(faulty_module, "test@example.com", client, results)
print(results)
# Output contains:
# [{
# "name": "faulty_module",
# "domain": "unknown",
# "rateLimit": False,
# "error": True,
# "exists": False,
# "emailrecovery": None,
# "phoneNumber": None,
# "others": None
# }]
asyncio.run(demo())
Running this snippet produces a standardized error entry for faulty_module while the event loop remains intact, proving that Holehe's architecture successfully isolates module failures from the overall execution context.
Summary
- Isolation: The
launch_modulecoroutine inholehe/core.pywraps each module in atry … except Exceptionblock to prevent cascading failures. - Logging: Failed modules produce a consistent JSON structure with
"error": True,"exists": False, andnulldata fields. - Continuity: The shared
outlist receives the error record, allowing remaining modules to execute normally. - Visibility: The
print_resultfunction renders red[!]indicators in terminal output to flag specific module failures.
Frequently Asked Questions
Does Holehe crash if a single module fails?
No. Holehe implements fail-soft behavior where the launch_module function catches all exceptions thrown by individual modules. The tool logs the failure and continues executing the remaining service checks without terminating the process or corrupting the results aggregation.
How does Holehe indicate a module error in the terminal output?
According to the source code in holehe/core.py, the print_result function checks for results["error"] and displays a red [!] marker next to the service name. This provides immediate visual distinction between execution failures and negative existence results.
Can I see the original exception traceback when a module fails?
The current implementation in holehe/core.py catches exceptions broadly without re-raising or logging the traceback to the standard output list. The error is silently captured and converted to a boolean flag, meaning the specific exception details are not preserved in the final results dictionary by default.
Where is the exception handling logic implemented?
The primary exception handling logic resides in holehe/core.py within the launch_module coroutine (approximately lines 66–78). This centralizes error management for all modules located in holehe/modules/, ensuring consistent behavior across the entire service catalog.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →