Skip to content

POST /api/v1/hgvs/validate returns 500 for malformed input #860

Description

@bencap

Summary

Malformed input to the HGVS validation endpoint returns HTTP 500 and fires a Slack error alert, when it should return a 4XX client error.

Problem

In hgvs_validate (in the hgvs router), the parser call hp.parse(variant["variant"]) runs outside the try/except. A syntactically invalid variant string raises HGVSParseError at the parse stage so it propagates to CatchAllErrorMiddleware and becomes a 500. Only HGVSInvalidVariantError, raised later at the validate stage, is caught today.

The free-form variant: dict[str, str] request body has the same failure mode: a request missing the variant key raises KeyError, also surfacing as a 500.

Both failures stem from caller-supplied input and should be 4XX.

Steps to reproduce

  1. POST /api/v1/hgvs/validate with body {"variant": "NM_001256054.2:c.-45+163GGGGCC[(145_?)]"} (or any unparseable HGVS string).
  2. POST /api/v1/hgvs/validate with body {}.

Expected: 400 for the unparseable string; 422 for the missing field.

Observed: 500 for both, each accompanied by a Slack error alert. The unparseable-string case logs HGVSParseError originating from the parse call in the hgvs router.

Proposed behavior

  • Move hp.parse() inside the error handler and catch the base class hgvs.exceptions.HGVSError, so any HGVS-level failure — unparseable string, inconsistent variant, unknown accession — returns 400. This matches the existing precedent that catches HGVSError in the dataframe variant validation library.
  • Replace the dict[str, str] body with a typed request view model exposing a required variant: str field. FastAPI then returns 422 for a missing or mistyped field automatically, and the request schema is self-documenting in OpenAPI. The field name stays variant, so there is no client contract change.
  • Update the endpoint's documented responses from the 400-only set to the combined validation set (400 + 422).

Acceptance criteria

  • An unparseable HGVS string returns 400, not 500.
  • A request body missing the variant field returns 422, not 500.
  • A valid-but-inconsistent variant still returns 400 (unchanged).
  • Neither input case triggers the 500-path Slack alert.
  • Router tests cover the unparseable-string (400) and missing-field (422) cases.

Implementation notes

  • Add the request model as a new hgvs view model (variant: str) extending the shared base model; its camelize alias generator leaves the single-word field as variant.
  • After the API change, regenerate the UI's OpenAPI schema types so they reflect the typed request body.

Metadata

Metadata

Assignees

Labels

app: backendTask implementation touches the backend

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions