Problem
Malformed query parameters such as ?hours=999, ?limit=abc, and ?start=garbage currently return 200 with silently coerced or defaulted values. While this prevents crashes (addressed in Issue #40), it bakes in a tolerant contract that is inconsistent with standard API error semantics.
Clients cannot distinguish between a valid empty result and a bad request. Any frontend or integration that passes a bad parameter receives no signal that it did anything wrong.
Examples
?hours=999 → clamped to 24 → returns 200 with meetings as if hours=24
?hours=0 → clamped to 24 → returns 200 with no indication the value was rejected
?limit=abc → defaulted to 1000 → returns 200 silently
?start=garbage → treated as current time → returns 200 silently
Current Impact
- Clients receive no signal when their request is malformed
- Bakes in a tolerant contract that is difficult to reverse once consumers depend on it
- Inconsistent with RFC 7807 and standard REST error semantics
- Blocks future input validation work (Issue pre-launch-03)
Proposed Solution
Return 400 Bad Request with an RFC 7807 problem-document body for out-of-bounds or unparseable parameter values. The existing express-http-problem-details and http-problem-details-mapper packages are already in the dependency tree and should be wired to the existing ReqParamFormatError custom error class.
Example response body:
{
"type": "https://example.com/problems/invalid-query-parameter",
"title": "Invalid Query Parameter",
"status": 400,
"detail": "hours must be an integer between 1 and 168"
}
Changes Required
- In
src/meetings.controller.ts: throw ReqParamFormatError instead of clamping out-of-bounds values
- In
src/common/error_mappers/: wire ReqParamFormatError to produce 400 + problem-document
- In
cypress/e2e/malformed-query-params.cy.ts: update assertions from 200 to 400
- In
cypress/e2e/meetings.cy.ts: update hours-clamping tests to assert 400
Acceptance Criteria
Notes
The ReqParamFormatError custom error class already exists in src/common/custom_errors/ but is not currently used. The error mapper chain already exists in server.ts. This issue connects those two existing pieces to actual traffic.
See also: Issue #42 which addresses broader validation beyond temporal parameters.
Problem
Malformed query parameters such as
?hours=999,?limit=abc, and?start=garbagecurrently return 200 with silently coerced or defaulted values. While this prevents crashes (addressed in Issue #40), it bakes in a tolerant contract that is inconsistent with standard API error semantics.Clients cannot distinguish between a valid empty result and a bad request. Any frontend or integration that passes a bad parameter receives no signal that it did anything wrong.
Examples
?hours=999→ clamped to 24 → returns200with meetings as if hours=24?hours=0→ clamped to 24 → returns200with no indication the value was rejected?limit=abc→ defaulted to 1000 → returns200silently?start=garbage→ treated as current time → returns200silentlyCurrent Impact
Proposed Solution
Return
400 Bad Requestwith an RFC 7807 problem-document body for out-of-bounds or unparseable parameter values. The existingexpress-http-problem-detailsandhttp-problem-details-mapperpackages are already in the dependency tree and should be wired to the existingReqParamFormatErrorcustom error class.Example response body:
{ "type": "https://example.com/problems/invalid-query-parameter", "title": "Invalid Query Parameter", "status": 400, "detail": "hours must be an integer between 1 and 168" }Changes Required
src/meetings.controller.ts: throwReqParamFormatErrorinstead of clamping out-of-bounds valuessrc/common/error_mappers/: wireReqParamFormatErrorto produce 400 + problem-documentcypress/e2e/malformed-query-params.cy.ts: update assertions from200to400cypress/e2e/meetings.cy.ts: update hours-clamping tests to assert400Acceptance Criteria
?hours=999returns 400 with problem-document?hours=0returns 400 with problem-document?limit=abcreturns 400 with problem-document?start=garbagereturns 400 with problem-documenttype,title,status,detail)malformed-query-params.cy.tsupdated to assert 400 instead of 200meetings.cy.tsupdated to assert 400 instead of 200Notes
The
ReqParamFormatErrorcustom error class already exists insrc/common/custom_errors/but is not currently used. The error mapper chain already exists inserver.ts. This issue connects those two existing pieces to actual traffic.See also: Issue #42 which addresses broader validation beyond temporal parameters.