HarperFast / HarperFast/harper

REST ?select projection crashes (500) on missing to-one relationship target and sub-select on non-relationship field

Open
#1,415 3 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.