Skip to content

fix(exceptions): log the full stack trace in the global exception handler - #204

Closed
tmgbedu wants to merge 1 commit into
mainfrom
task/exc-handler-stacktrace-1347
Closed

fix(exceptions): log the full stack trace in the global exception handler#204
tmgbedu wants to merge 1 commit into
mainfrom
task/exc-handler-stacktrace-1347

Conversation

@tmgbedu

@tmgbedu tmgbedu commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Problem

The global ExceptionHandler.report_exception() builds its log message via _build_context(), which only appended the traceback when the app was in debug mode. In production the ERROR log carried just the exception summary — e.g. ModuleNotFoundError: No module named 'app.agents.chat' — with no stack trace, so failures were effectively undiagnosable from logs.

Fix

_build_context() now always returns the full traceback.format_exception(...) output (matching the module's existing traceback convention). Whether the trace is shown to the HTTP client remains a separate, debug-gated decision in the FastAPI render layer (fastapi/exceptions.py), so this does not leak internals to end users — it only enriches server-side logs / stderr.

Tests

New tests/exceptions/test_handler.py:

  • traceback is logged when not in debug (the regression),
  • traceback is logged in debug too,
  • traceback is printed to stderr when no logger is bound.

uv run pytest (excl. live-Postgres): 2053 passed, 7 skipped. Ruff clean.

Task #1347.

report_exception() built its log context via _build_context(), which only
appended the traceback when the app was in debug mode. In production the ERROR
log carried just 'ExcType: message' (e.g. 'ModuleNotFoundError: No module named
app.agents.chat') with no stack trace, making failures hard to diagnose.

Always include the full traceback in the logged/stderr context. Exposing the
trace to the HTTP client stays a separate, debug-gated decision in the FastAPI
render layer, so this doesn't leak internals to users.

Add tests asserting the traceback is logged in both non-debug and debug modes,
and printed to stderr when no logger is bound.
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@tmgbedu

tmgbedu commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

Code review — PASS (task #1349)

Reviewed the diff, the render-layer for client exposure, and the new tests. (Note: posting as a comment, not an approval review, since GitHub won't let this account approve its own PR.)

Correctness

  • _build_context() now unconditionally returns traceback.format_exception(...), fixing the original bug where production logs only got ExcType: message with no trace.
  • Confirmed no other callers of _build_context/report_exception exist, so this is an isolated, safe change.

No client-facing leakage

  • Checked fastapi/exceptions.py::HTTPExceptionHandler.render() — the HTTP response body is still gated on app.is_debug() and only returns {"message": "Server Error"} when not in debug. This PR only touches the server-side logging path (report_exceptionLogger.error/stderr); the debug gate for what the client sees is untouched.

Tests

  • Ran tests/exceptions/test_handler.py in isolation: 3/3 pass, covering the non-debug regression, debug-mode logging, and the no-logger stderr fallback.
  • Ran the full suite (uv run pytest --ignore=tests/masoniteorm/postgres): 2053 passed, 7 skipped — matches the PR description.
  • ruff check clean on changed files.
  • The uv.lock diff just re-syncs the editable package's self-referential version metadata to match pyproject.toml (already 0.50.0 on both branches) — harmless, unrelated to the fix itself.

LGTM. Holding off on merge until QA (task #1348) signs off, per the coordination task.

@tmgbedu tmgbedu closed this Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant