Skip to content

remote embedding provider: malformed JSON response throws raw SyntaxError instead of EngineError #1745

Description

@carlos-alm

Summary

In src/domain/search/providers/remote.ts, embedRemote()'s response.json() call sits outside the try/catch that wraps the fetch() call. Every other failure mode in this function (abort/timeout, network failure, non-2xx status, missing/wrong-shape embedding field, dimension mismatch) is normalized into a descriptive EngineError naming the endpoint — but a 200 OK response with a malformed/non-JSON body (e.g. an HTML error page from a misconfigured proxy in front of the embeddings endpoint) throws a raw uncaught SyntaxError instead, breaking the otherwise-consistent error contract of this remote API boundary.

Where

src/domain/search/providers/remote.ts, in embedRemote (originally line 128, now inline in the per-batch loop right after calling the extracted executeRemoteEmbeddingRequest helper):

const json = (await response.json()) as OpenAIEmbeddingResponse;

Origin

Flagged by titan-gauntlet audit of this file (rule 2, pillar I) with recommendation: "move response.json() inside error handling so a malformed body produces the same EngineError contract as every other failure path."

Why not fixed inline

Phase 13 of the titan-forge run scoped to this file was explicitly restricted to a pure behavior-preserving decomposition (split embedRemote into a request-executor + response-validator, extract-method only — see commit "refactor: split embedRemote into request-executor and response-validator in remote.ts"). Folding in this error-handling behavior change would have mixed a bug fix into a refactor commit and risked masking a real behavior change as "just a decomposition." Filing this issue per the project's scope-discipline rule instead of guessing at intent.

Suggested fix

Wrap const json = (await response.json()) as OpenAIEmbeddingResponse; in a try/catch (or fold it into the request-executor / a small helper) that re-throws a SyntaxError/parse failure as an EngineError with a message consistent with the other failure paths in this function, e.g.:

Remote embedding endpoint <url> returned a response that could not be parsed as JSON: <message>

Should be covered by a new test mocking fetch to resolve with a non-JSON body (e.g. new Response('<html>...</html>', { status: 200 })) and asserting embedRemote rejects with EngineError rather than SyntaxError.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions