HarperFast / HarperFast/harper
REST ?select projection crashes (500) on missing to-one relationship target and sub-select on non-relationship field
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
## Summary
Two distinct crashes in the REST `?select` query-projection path return HTTP 500 for client errors that should be 4xx. Both are in `resources/Resource.ts`.
## Locus A — `null`/`undefined` to-one relationship target (`Resource.ts:801`)
A `?select(rel{field})` on a to-one relationship where the referent record doesn't exist (orphaned FK) or is `null` → `TypeError: Cannot read properties of null (reading 'field')`. The projection mapper at line 801 calls into the resolved relationship object without a null-guard.
**Repro:**
```
GET /Parent/?select(child{name})
```
where `.childId` references a deleted or non-existent child.
Expected: `null` (or omit the field), `200`.
Actual: `500 TypeError: Cannot read properties of null`.
## Locus B — Sub-select on scalar / unknown / computed field (`Resource.ts:831 → Table.ts:776`)
A `?select(plainField{subField})` where `plainField` is a scalar attribute (not a `@relationship`) or a computed/unknown name → `TypeError: Cannot read properties of undefined (reading 'propertyResolvers')` at `Resource.ts:831` / `Table.ts:776`. The sub-select resolver dereferences `tableClass` without first checking if the selected name resolves to a table/relationship type.
**Repro:**
```
GET /T/?select(nonExistentRel{x})
GET /T/?select(scalarField{x})
```
Expected: `400 Bad Request` (unknown field or invalid sub-select).
Actual: `500 TypeError`.
## Related
Both loci are instances of the systemic "client errors surface as HTTP 500" pattern noted on #1299 (GraphQL), #1397 (SQL), and F-031 (ops-API). The to-one null case (locus A) is also documented in D-066 (doc gap: behavior on missing relationship targets is undocumented for `?select`).
**Harper:** `7aaa5a152`; `Resource.ts` / `Table.ts` byte-identical to `main` @`6797f091d`.
**Repro test:** `integrationTests/qa-scratch/qa152-rest-select.test.ts`
---
*Surfaced by the QA-explorer exploratory campaign for @kris (QA-152). Filed by Claude (Sonnet 4.6) for @kris.*
Contributor guide
Research direction
Start with integrationTests/qa-scratch/qa152-rest-select.test.ts, then inspect the projection paths at Resource.ts:801 and Resource.ts:831 and the related Table.ts:776 call. Add regression coverage for missing to-one targets and invalid scalar or unknown sub-selects; done means the former returns 200 with a null or omitted field and the latter returns 400 instead of 500.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nodejs, typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100