alibaba/page-agent · error · InvokeError
INVALID_RESPONSE
INVALID_RESPONSE
Error message
Response body is not valid JSON
What it means
The HTTP request succeeded but response.json() failed — the response body is not valid JSON. This usually means the baseURL actually points at an HTML page, a proxy error page, or an empty/SSE stream rather than a JSON API. The parse error is attached as cause.
Source
Thrown at packages/llms/src/OpenAIClient.ts:135
InvokeErrorTypes.SERVER_ERROR,
`Server error: ${errorMessage}`,
errorData
)
}
throw new InvokeError(
InvokeErrorTypes.UNKNOWN,
`HTTP ${response.status}: ${errorMessage}`,
errorData
)
}
// 4. Parse and validate response
let data: any
try {
data = await response.json()
} catch (error) {
if ((error as any)?.name === 'AbortError') throw error
throw new InvokeError(
InvokeErrorTypes.INVALID_RESPONSE,
'Response body is not valid JSON',
error
)
}
const choice = data.choices?.[0]
if (!choice) {
throw new InvokeError(InvokeErrorTypes.INVALID_SCHEMA, 'No choices in response', data)
}
// Check finish_reason
switch (choice.finish_reason) {
case 'tool_calls':
case 'function_call': // gemini
case 'stop': // some models use this even with tool calls
break
case 'length':View on GitHub (pinned to d02db1ee7c)
Solutions
- curl the exact URL with a sample body and inspect Content-Type and the raw response
- Fix baseURL to the JSON chat/completions endpoint including the /v1 path
- If the endpoint only supports streaming, ensure the request is configured so the server returns a single JSON object (no stream:true)
- Check for proxies/CDNs injecting HTML pages
Example fix
// before
new OpenAIClient({ baseURL: 'https://openai.com' }) // returns HTML
// after
new OpenAIClient({ baseURL: 'https://api.openai.com/v1' }) Defensive patterns
Strategy: type-guard
Validate before calling
// confirm the endpoint returns JSON before wiring the client
const r = await fetch(cfg.baseURL + '/models', { headers: { Authorization: `Bearer ${cfg.apiKey}` } })
const ct = r.headers.get('content-type') ?? ''
if (!ct.includes('application/json')) throw new Error(`Expected JSON, got ${ct}`) Type guard
const isInvalidJsonError = (e: unknown): e is InvokeError => e instanceof InvokeError && e.code === 'INVALID_RESPONSE' && /not valid JSON/.test(e.message)
Try / catch
try {
await client.invoke(req)
} catch (e) {
if (isInvalidJsonError(e)) throw new Error(`baseURL likely points at a non-API page: ${cfg.baseURL}`)
throw e
} Prevention
- Validate baseURL against the documented API path, not the website URL
- Beware CDNs/proxies serving HTML interstitials with 200
- Avoid stream:true with this client — it expects a single JSON body
When it happens
Trigger: invoke() where the server returns HTML (login page, 200-redirected captive portal, Cloudflare interstitial), plain text, or an empty body with 200; pointing baseURL at a UI page instead of the API path; a gateway returning a non-JSON maintenance page.
Common situations: baseURL pointed at the provider's website instead of the API endpoint; reverse proxy serving an HTML error/landing page with 200; streaming endpoints that return SSE when the client expects a single JSON body; server truncating the response.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
AI-assisted analysis of alibaba/page-agent@d02db1ee7c (2026-08-28).
Data as JSON: /api/errors/3ee331bfe682a10f.
Report an issue: GitHub.