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
POST /api/v1/hgvs/validate with body {"variant": "NM_001256054.2:c.-45+163GGGGCC[(145_?)]"} (or any unparseable HGVS string).
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.
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 thehgvsrouter), the parser callhp.parse(variant["variant"])runs outside thetry/except. A syntactically invalid variant string raisesHGVSParseErrorat the parse stage so it propagates toCatchAllErrorMiddlewareand becomes a 500. OnlyHGVSInvalidVariantError, 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 thevariantkey raisesKeyError, also surfacing as a 500.Both failures stem from caller-supplied input and should be 4XX.
Steps to reproduce
POST /api/v1/hgvs/validatewith body{"variant": "NM_001256054.2:c.-45+163GGGGCC[(145_?)]"}(or any unparseable HGVS string).POST /api/v1/hgvs/validatewith 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
HGVSParseErrororiginating from the parse call in thehgvsrouter.Proposed behavior
hp.parse()inside the error handler and catch the base classhgvs.exceptions.HGVSError, so any HGVS-level failure — unparseable string, inconsistent variant, unknown accession — returns 400. This matches the existing precedent that catchesHGVSErrorin the dataframe variant validation library.dict[str, str]body with a typed request view model exposing a requiredvariant: strfield. FastAPI then returns 422 for a missing or mistyped field automatically, and the request schema is self-documenting in OpenAPI. The field name staysvariant, so there is no client contract change.responsesfrom the 400-only set to the combined validation set (400 + 422).Acceptance criteria
variantfield returns 422, not 500.Implementation notes
hgvsview model (variant: str) extending the shared base model; itscamelizealias generator leaves the single-word field asvariant.