HarperFast / HarperFast/harper
Operations API: ~25 malformed/wrong-type/out-of-range inputs return HTTP 500 instead of 4xx
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
## Summary
A systematic fuzz of the operations API (59 representative calls) found **25 that return HTTP 500** for inputs that are clearly client errors — malformed payloads, wrong-typed arguments, unknown operation variants, out-of-range values. The expected status for all is 4xx (400/422).
## Sample of 500-returning inputs
| Operation | Bad input | Expected | Actual |
|---|---|---|---|
| `set_configuration` | unknown key | 400 | 200 (silent drop) |
| `set_configuration` | `http.maxHeaderSize: -1` (accepted, bricks boot) | 400 | 200 / 500 on restart |
| `insert` | `records: "not-an-array"` | 400 | 500 |
| `insert` | `records: [42]` (non-object element) | 400 | 500 |
| `update` | `records: null` | 400 | 500 |
| `upsert` | missing `table` key | 400 | 500 |
| `upsert` | `table: 12345` (integer) | 400 | 500 |
| `search_by_conditions` | degenerate single-child `or` | 400 | 500 |
| `search_by_conditions` | `limit: "ten"` | 400 | 500 |
| `search_by_value` | `limit: -5` | 400 | 500 |
| `bulk_load` | `path` points to a non-existent file | 400 | 500 |
| `drop_table` | non-existent table | 400 | 500 |
| `csv_data_load` | `csv_file_path` missing | 400 | 500 |
(25 of 59 tested; the table above is a representative sample — full list in the qa-scratch test output.)
## Pattern
The common thread is that Joi validation (the first layer) catches type and enum errors but has incomplete coverage for range constraints (numeric min/max), missing-but-required sub-keys, and wrong-shape values inside arrays. When Joi passes an input that the engine then rejects, the engine throws an unguarded `Error` that bubbles to 500.
This is the same "client errors as HTTP 500" pattern noted on #1299 (GraphQL auth), #1397 (SQL unsupported constructs), and F-030 (REST `?select`).
## Recommendation
- Add a Joi (or equivalent) validation pass that returns 4xx before the operation reaches the engine for the missing-required / wrong-type / out-of-range cases listed above.
- Alternatively, an error-class convention where the engine throws a typed `ClientError` subclass that the transport layer maps to 400.
- Long-term: a single "client error → 4xx" middleware pass would close all instances of this pattern across REST, GraphQL, SQL, and ops-API.
**Harper:** `7aaa5a152`; byte-identical to `main` @`6797f091d`.
**Repro test:** `integrationTests/qa-scratch/qa147-ops-fuzz.test.ts`
---
*Surfaced by the QA-explorer exploratory campaign for @kris (QA-147). Filed by Claude (Sonnet 4.6) for @kris.*
Contributor guide
Research direction
Start by running integrationTests/qa-scratch/qa147-ops-fuzz.test.ts and reviewing the Operations API validation and error-handling entry points it exercises. Compare the listed malformed, wrong-type, missing-key, and out-of-range cases with the current Joi checks and transport responses. Done means the identified client-error inputs return 4xx responses instead of 500, without changing valid operation behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js, typescript
- Domain
- api, backend, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100