HarperFast / HarperFast/harper

REST iterable responses swallow generator throws into an in-band {"error"} array element with HTTP 200

Open
#2,392 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
89
Forks
10
Avg merge
2d 6h
Merged PRs (30d)
200

Description

## What happens

A REST iterable response (custom Resource returning an async iterator) whose generator **throws** mid-serialization delivers the error as an in-band `{"error": "..."}` **array element** with HTTP 200. A client doing `res.ok && await res.json()` silently treats the error as a data row: mid-stream the payload is `[{"n":0},{"n":1},{"error":…}]` — indistinguishable from a 3-row result without schema knowledge. For the pre-first-yield case nothing has been committed to the wire yet and a real 500 is freely available, so at minimum that case is indefensible.

## Mechanism (on `origin/main` @ e16d9616)

`server/serverHelpers/JSONStream.ts` (moved from `resources/JSONStream.ts`) — `serialize()`'s generator `catch (error)` turns any iterator throw, sync or async, pre- or post-first-yield, into `{ done: false, value: { error: errorToString(error) } }` and continues the array serialization; nothing changes the eventual HTTP status.

## Suggested fix shape

- Pre-first-byte: propagate the error → real 4xx/5xx.
- Post-first-byte (status already committed): terminate the stream *abnormally* rather than emitting a well-formed array close around an in-band error object — the SSE/NDJSON error contract pinned in `integrationTests/server/stream-error-contract.test.ts` (PR #2070) is the precedent; the JSON-array surface is the one that still lies.

## Existing work checked

#1650 is the `[Epic] HTTP error-hygiene` umbrella with no body detail — no dedicated issue describes this mechanism. #2329 (F-275) is a sibling on a different path (`transformIterable`/SSE/NDJSON `writeHead` timing at `server/http.ts:621`), not a dup. Searched harper + harper-pro, open+closed, for JSONStream / swallowed generator throw: nothing else on point.

## What this does not prove

GraphQL and MCP iterable surfaces were not exercised; only the REST JSON-array path is confirmed.

---
*From dispatch QA finding F-277, verified against harper origin/main e16d9616, 2026-08-29.*

Contributor guide

Open the contributing guide

Research direction

Start with server/serverHelpers/JSONStream.ts, especially serialize() and its generator catch, then read integrationTests/server/stream-error-contract.test.ts and the REST iterable response path. Done means pre-first-byte iterator failures produce a real 4xx/5xx, while post-first-byte failures terminate abnormally without emitting an in-band error element or a normal array close.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.