Audit pipeline that detects unsafe exception handling in LLM‑generated Python code
Project description
Silent Killers
An Exploratory Audit of Exception‑Handling in LLM‑Generated Python
tl;dr We show that large‑language models often add
try/exceptblocks that silently swallow errors. Our AST‑based metric pipeline lets anyone quantify that risk across thousands of generated scripts in seconds.
1 Quick start
$ printf "try:\n print(10 / 0)\nexcept:\n pass\n" > bad_block_example.py
$ printf "print('this is a line') ; new_variable = 123 ; print('this code is fine')" > safe_example.py
$ pip install silent-killers
$ silent-killers-audit bad_block_example.py
❌ example.py: 1 bad exception block(s) found on line(s): 3
$ silent-killers-audit safe_example.py
$
1.1 Use in pre-commit
Add this to .pre-commit-config.yaml:
- repo: https://github.com/kilojoules/silent-killers
rev: v0.1.7
hooks:
- id: silent-killers-audit
1.2 Library usage
from silent_killers.metrics_definitions import code_metrics
python_code = "try:\n 1/0\nexcept Exception:\n pass"
for metric in code_metrics(python_code):
print(metric.name, metric.value)
loc 4
exception_handling_blocks 1
bad_exception_blocks 1
bad_exception_locations [3]
pass_exception_blocks 1
total_pass_statements 1
bad_exception_rate 1.0
uses_traceback False
parsing_error # None
2 Installation
git clone https://github.com/kilojoules/silent-killers.git
cd silent-killers
python -m pip install --upgrade pip
pip install -e .
or using the pypi distribution
pip install silent-killers
Requires Python ≥ 3.10
Runtime deps:pandas,numpy,matplotlib
3 Repository layout
repo-root/
├─ src/
│ └─ silent_killers/ ← reusable package
│ ├─ __init__.py
│ └─ metrics_definitions.py (AST visitors & regex metrics)
│ └─ llm_api.py (interface analysis with different LLM APIs)
├─ tests/ ← reusable package unit tests
│ └─ test_exception_labels.py
│
├─ scripts/ ← analysis scripts
│ ├─ process_files.py (generates metrics CSVs)
│ └─ post_processing.py (creates plots & summary tables)
│ └─ run_experiments.py (runs the 3 prompts using the models in models.yaml)
│
├─ data/ ← study‑specific artifacts
│ ├─ calibration_prompt/ (easy rewrite task)
│ ├─ propagation_prompt/ (medium rewrite task)
│ ├─ optimization_prompt/ (hard rewrite task)
│ └─ figures/ (output plots & visualizations)
│
├─ pyproject.toml
|
└─ README.md
4 Scope of this study
Modern LLMs can write Python that “runs”, but how it fails matters.
A bare except: or a blanket except Exception: with no
re‑raise can mask fatal bugs, leading to silent data corruption or
debugging nightmares—these are the silent killers.
We collected 5 seeds × 8 models × 3 prompts (easy → hard rewrite tasks) and asked:
- How often do models inject
try/exceptat all? - Of those, how many are “bad” under a strict re‑raise rule?
- Does difficulty exacerbate the problem?
The full paper is on my portfolio: https://julianquick.com/ML/llm-audit.html.
5 Metrics at a glance
| metric | description |
|---|---|
exception_handling_blocks |
count of except clauses |
bad_exception_blocks |
bare except: or except Exception: without raise |
bad_exception_rate |
bad / total, 2 dp |
uses_traceback |
calls traceback.print_exc() / .format_exc() |
| … | see src/silent-killers/metrics_definitions.py |
6 Key pilot finding
When a model adds any error handling, 50–100 % of those handlers are unsafe.
Inclusive bad‑rates look tame (0 – 0.6) but conditional bad‑rates (only_with_try) spike to 1.0 for several models on simple prompts.
For these reasons, we recoomend using the silent-killers-audit tool in pre-commit workflows.
7 Development
ruff check . # lint
pytest # run unit tests
coverage run -m pytest && coverage html
CI runs on GitHub Actions across Python 3.10 and 3.11 (see .github/workflows/ci.yml).
8 Roadmap
- 🚧 dynamic execution traces (runtime errors, coverage)
- 🚧 extend to other unsafe patterns
- 🚧 support more languages than Python
PRs & issues welcome!
9 License & citation
MIT License.
If you use the metrics or figures, please cite:
@misc{Quick2025SilentKillers,
title = {Silent Killers: An Exploratory Audit of Exception‑Handling in LLM‑Generated Python},
author = {Julian Quick},
year = {2025},
url = {https://github.com/kilojoules/silent-killers}
}
Happy auditing – don’t let silent errors slip through!
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file silent_killers-0.1.8.tar.gz.
File metadata
- Download URL: silent_killers-0.1.8.tar.gz
- Upload date:
- Size: 12.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
343d36f58c8aba0c740d85b84d4d2046e2014edb92feb292b4e202a13a21411b
|
|
| MD5 |
18ad167a1f7325857925d10104fd93b6
|
|
| BLAKE2b-256 |
088fe2e888380889478d34c47c29afeb6c4287803914af92a386d898fed775a7
|
File details
Details for the file silent_killers-0.1.8-py3-none-any.whl.
File metadata
- Download URL: silent_killers-0.1.8-py3-none-any.whl
- Upload date:
- Size: 8.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46bf9cffd73e822806e70f0302888501769ec18194b88d84c2bb02ae2259ec43
|
|
| MD5 |
4690a135ad21cc945bbd9133cbf85102
|
|
| BLAKE2b-256 |
be1037b5aa1f04082604b685062502d4f210ade2807e375f3fb8a999c6a882d8
|