Skip to content

tech-debt(api): create_success_response returns a Pydantic model — 500s under response_model=Dict[str, Any] if not .model_dump()'d #10234

Closed

Description

@mrveiss

Context

utils/response_helpers.py create_success_response() returns a DataResponse[T] Pydantic model, not a dict. An endpoint that declares response_model=Dict[str, Any] and does return create_success_response(...) directly raises FastAPI ResponseValidationError → 500 on success (Pydantic v2 won't coerce a model to dict). Confirmed empirically (raw → 500, .model_dump(mode="json") → 200).

This already shipped broken in api/chat_shared_links.py (every endpoint 500'd on success, undetected — no runtime tests). Fixed there in PR #10233 by .model_dump(mode="json")-ing each result.

Footgun

The bug ONLY manifests with response_model=Dict[str, Any] and an un-dumped return. Without a Dict response_model, FastAPI json-encodes the model fine. So it's easy to introduce silently.

Recommendation (preventive — no current broken instances remain)

Pick one convention and document/lint it:

  • (a) make create_success_response return a plain dict (broadest fix, but check all call sites that may rely on the model), OR
  • (b) drop response_model=Dict[str, Any] on these endpoints (let FastAPI encode the model), OR
  • (c) a CI grep guard for return create_success_response( directly under a response_model=Dict[str, Any] route.

Found during #9929 / PR #10233 (#8996 completion).

Activity

  1. added a commit that references this issue on Jun 21, 2026
  2. github-actions commented on Jun 21, 2026

    @github-actions
    Contributor

    PR #10402 (merged to Dev_new_gui) references this issue with a close keyword.

    complete #9922 tail: footgun guard, health composable contract, system-status resilience, formatter hardening (#10234, #10119, #10347, #10208)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  3. mrveiss commented on Jun 21, 2026

    @mrveiss
    OwnerAuthor

    Resolved — merged as ae7951628 (PR #10402). Added an AST pytest guard (tests/api/test_response_helper_footgun.py) that fails if any route reintroduces the response_model=Dict[str,Any] + un-dumped create_success_response 500 footgun. Zero behavior change; proven to catch a reintroduction.

  4. added a commit that references this issue on Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions