ErrLookup › Background articles › "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong
"invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong
"invalid response format", "malformed payload", and "missing data field" errors all belong to one family: the HTTP request succeeded, the body parsed as JSON, but the payload does not have the structure the library expects — a missing field, a non-array where an array was expected, or an error envelope served with a 200 status. Developers hit these errors when an upstream API changes its schema, a proxy or CDN substitutes its own response, an auth session silently expired, or an error body masquerades as a success payload.
Distilled from 106 documented records across 23 repositories.
Background
This family sits at a specific layer: after the network call succeeds and after JSON parsing succeeds, but before the library hands data to your code. The HTTP status was 2xx, resp.json() or JSON.parse didn't throw, and yet the decoded value is missing a key, has a field of the wrong type, or has the wrong top-level shape (an array or string where an object was expected, null where a list was expected). Libraries raise these errors deliberately as contract guards: rather than silently returning an empty result or crashing later on a TypeError deep inside mapping code, they validate the envelope once and fail with a descriptive message. Record [1] states the intent plainly — the throw exists so callers can assume payload.field access is safe.
Why do 200 responses carry wrong-shaped bodies at all? The records converge on a handful of mechanisms. Upstream APIs serve error envelopes with success statuses: GitHub device-flow errors delivered with 200 [13], DashScope throttled responses with non-standard bodies [24], Alpha Vantage signaling errors through JSON keys rather than HTTP statuses [18], GraphQL returning a top-level errors array alongside null data [6][21]. Auth layers degrade quietly: an expired Pixiv or BOSS session or a logged-out Manus profile yields an error envelope or login page instead of the real payload [2][14][23]. Intermediaries interfere: proxies, CDNs, WAFs, and SSL-inspecting middleboxes substitute HTML error pages, cached JSON, or re-encoded bodies [3][7][12][24]. And finally, the API itself changes — fields get renamed, envelopes get restructured, query IDs go stale.
From the caller's side these errors look uniform but mean different things. Some libraries embed a truncated raw payload in the message to make diagnosis instant — OpenCLI's Douyin error includes the first 500 characters of the response [10], career-ops embeds 200 characters of the run-creation body [12], and the Mastra Kimi error names the operation that failed [29]. Others leave you to log the body yourself. The strictness also varies: some checks demand exact types (a string token and numeric expires_at in Copilot token validation [16], an integer 0/1 from a Lua restore script [17]), while others accept any of several known keys (OpenCLI's Manus skills check accepts userAddedSkills, systemSkills, or skills [8]) or deliberately distinguish an empty-but-valid payload ([] for an empty Apify dataset [5]) from a structurally wrong one.
A recurring distinction across the family is between contract drift and caller mistakes. Several records explicitly note that reaching the shape check means earlier error paths were already handled — Sourcegraph's GraphQL errors array is consumed before the missing-data check fires [6], Alpha Vantage's Note/Information/ErrorMessage keys are handled before the missing bestMatches case [18], and ONES' business-error fields are checked before the missing-groups case [11]. So when this error fires, it usually means something outside the documented error vocabulary happened: schema drift, a proxy in the path, or an auth state the library didn't anticipate.
Common causes
- Error envelope served with a 200 status. The API returned a JSON body describing a failure — an OAuth error object, a throttled response, a GraphQL errors array with null data — but with a success status code, so the library's status check passes and the shape check trips instead. Seen with GitHub device flow, DashScope, Alpha Vantage, and Copilot token endpoints.
- Expired or invalid session/auth state. A stale cookie, PHPSESSID, or logged-out browser profile makes the endpoint return a login/error envelope instead of the real payload. Records for Pixiv, BOSS, Manus, and Twitter recommend re-authenticating first because soft auth failures commonly masquerade as malformed responses.
- Proxy, CDN, WAF, or gateway interference. An intermediary substitutes its own response — an HTML error page with status 200, cached or partial JSON, or a re-encoded body (e.g. a stringified array instead of a parsed one). Multiple records tell you to hit the endpoint directly with curl to rule this out.
- Upstream API schema change. The provider renamed or restructured response fields: a messages field moved, an envelope nested differently, a query ID went stale, or an internal API version evolved. This is the case the guard was built for — update the parsing logic or the library/SDK to the version tracking the new shape.
- Wrong resource type or request parameters. The request targets something the endpoint doesn't serve in the expected shape: a collection instead of a concrete archive.org item, a ugoira instead of a regular illustration, an empty search keyword, an invalid team UUID, or too-broad a query triggering a search alert that omits results.
- Endpoint or version mismatch. The configured base URL points at a proxy or wrong deployment (ONES SSO gateway, self-hosted Sourcegraph with a different version, a GHES instance whose device-flow payload lags github.com), so the response follows a different schema than the library expects.
- Transient server-side degradation. Partial or degraded responses during deploys or outages — archive.org partial metadata, mid-deploy Manus payloads, empty data arrays. Several records note these often resolve on a simple retry.
What usually fixes it
- [object Object]
- [object Object]
- [object Object]
- [object Object]
- [object Object]
- [object Object]
Go deeper
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Documented occurrences
- archive item returned malformed payload: files must be an array (jackwener/OpenCLI)
- Chess.com API returned an unexpected payload shape for ${url} (jackwener/OpenCLI)
- Pixiv pages API returned malformed payload (jackwener/OpenCLI)
- Redis refresh-attempt consume returned an invalid response (koala73/worldmonitor)
- INVALID_RESPONSE_FORMAT: INVALID_RESPONSE_FORMAT (linshenkx/prompt-optimizer)
- Apify run ${runId} returned non-array dataset payload (santifer/career-ops)
- invalid response format: missing data field (charmbracelet/crush)
- Redis EVAL returned an invalid response (koala73/worldmonitor)
- Manus skills returned a malformed API payload (jackwener/OpenCLI)
- Flomo API returned a malformed response (jackwener/OpenCLI)
- 抖音封面申请上传地址响应缺少 UploadHost/StoreUri: ${JSON.stringify(applyRes).slice(0, 500)} (jackwener/OpenCLI)
- FETCH_ERROR: Unexpected filters/peek response (missing groups) (jackwener/OpenCLI)
- Apify did not return a run id: ${JSON.stringify(body).slice(0, 200)} (santifer/career-ops)
- Invalid device code response fields (mastra-ai/mastra)
- Boss recruiter history response did not include a message list (jackwener/OpenCLI)
- No project ID found in response (decolua/9router)
- Invalid Copilot token response fields (mastra-ai/mastra)
- Redis refresh-attempt restore returned an invalid response (koala73/worldmonitor)
- No data returned from search endpoint (we-promise/sure)
- Invalid Kimi For Coding device authorization response (mastra-ai/mastra)
…and 86 more across the corpus — use search.
Honest provenance: generated on 2026-08-30 from AI-assisted analysis of the linked records. See how records are made.