app/utils/checks_playbooks.py _resolve_file calls .resolve(strict=True) before any existence handling, so a missing playbook raises an uncaught FileNotFoundError → HTTP 500, despite the docstring promising :raises HTTPException: 400 ... or the file does not exist.
POST /v0/admin/run/bundles/nonexistent_bundle/run -> 500 Internal Server Error
Pre-existing, but #113 sharply increased the exposure: the hardcoded /core/* bundle routes are gone, so every bundle invocation now goes through the arbitrary {bundles_name:path} lookup, where a typo is the normal failure mode rather than an edge case. A 500 also gives the caller no way to distinguish "you named a bundle that doesn't exist" from "the server broke".
Fix: catch FileNotFoundError in _resolve_file and raise HTTPException(400) (or a Range42Error) with the resolved name, matching the format-validation failures alongside it.
Note tests/test_checks_playbooks.py::test_accepts_dotted_segment_format currently asserts pytest.raises(FileNotFoundError) — deliberately, since that is what makes the test non-vacuous today. It will need updating in lockstep with this fix.
app/utils/checks_playbooks.py_resolve_filecalls.resolve(strict=True)before any existence handling, so a missing playbook raises an uncaughtFileNotFoundError→ HTTP 500, despite the docstring promising:raises HTTPException: 400 ... or the file does not exist.Pre-existing, but #113 sharply increased the exposure: the hardcoded
/core/*bundle routes are gone, so every bundle invocation now goes through the arbitrary{bundles_name:path}lookup, where a typo is the normal failure mode rather than an edge case. A 500 also gives the caller no way to distinguish "you named a bundle that doesn't exist" from "the server broke".Fix: catch
FileNotFoundErrorin_resolve_fileand raiseHTTPException(400)(or aRange42Error) with the resolved name, matching the format-validation failures alongside it.Note
tests/test_checks_playbooks.py::test_accepts_dotted_segment_formatcurrently assertspytest.raises(FileNotFoundError)— deliberately, since that is what makes the test non-vacuous today. It will need updating in lockstep with this fix.