can1357/oh-my-pi · error · SearchProviderError

Jina API returned invalid response: expected an object or ar

Error message

Jina API returned invalid response: expected an object or array

What it means

Thrown by callJinaSearch when a 2xx response body from the Jina search API is neither a JSON array of results nor a JSON object (e.g. null, a string, a number). The provider's contract is that Jina returns either a bare results array or an envelope object with code/data, so anything else is treated as an invalid upstream response with no status code.

Source

Thrown at packages/coding-agent/src/web/search/providers/jina.ts:83

	if (site) headers["X-Site"] = site;
	headers["X-Respond-With"] = "no-content";
	headers["X-Retain-Images"] = "none";
	const response = await fetchImpl(requestUrl, {
		headers,
		signal: withHardTimeout(signal, timeoutMs),
	});

	if (!response.ok) {
		const errorText = await response.text();
		const classified = classifyProviderHttpError("jina", response.status, errorText);
		if (classified) throw classified;
		throw new SearchProviderError("jina", `Jina API error (${response.status}): ${errorText}`, response.status);
	}

	const payload = (await response.json()) as JinaSearchEnvelope | JinaSearchResponse | null;
	if (Array.isArray(payload)) return payload;
	if (!payload || typeof payload !== "object") {
		throw new SearchProviderError("jina", "Jina API returned invalid response: expected an object or array");
	}
	if (typeof payload.code === "number" && payload.code !== 200) {
		throw new SearchProviderError("jina", `Jina API response reported failure (${payload.code})`, payload.code);
	}
	if (!Array.isArray(payload.data)) {
		throw new SearchProviderError("jina", "Jina API returned invalid response: expected data array");
	}
	return payload.data as JinaSearchResponse;
}

/** Execute Jina web search. */
export async function searchJina(params: JinaSearchParams): Promise<SearchResponse> {
	const numResults = clampNumResults(params.num_results, DEFAULT_NUM_RESULTS, MAX_NUM_RESULTS);
	const keyOrResolver: ApiKey = params.authStorage.resolver("jina", {
		sessionId: params.sessionId,
	});
	const response = await withAuth(
		keyOrResolver,

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry the request; a 200-with-junk body is often transient middleware behavior.
  2. Bypass proxies/interceptors so the raw Jina JSON reaches the client.
  3. Verify network egress isn't a captive portal or hijacking DNS for s.jina.ai.
  4. Update the package if Jina changed its response envelope; the parser is updated alongside their API.

Example fix

// before: test stub returning junk
const fetchImpl = async () => new Response(null, { status: 200 });
// after: envelope-shaped stub
const fetchImpl = async () => new Response(JSON.stringify({ code: 200, data: [] }), { status: 200 });
Defensive patterns

Strategy: validation

Type guard

function isJinaResultsPayload(p: unknown): p is { code?: number; data: unknown[] } | unknown[] {
  return Array.isArray(p) || (typeof p === 'object' && p !== null && Array.isArray((p as { data?: unknown }).data));
}

Try / catch

try {
  return await search({ provider: 'jina', query });
} catch (err) {
  if (err instanceof SearchProviderError && err.message.includes('invalid response')) {
    return await retryWithBackoff(() => search({ provider: 'jina', query }));
  }
  throw err;
}

Prevention

When it happens

Trigger: response.json() on a 200 response resolves to null, a string, or a number instead of an array or object — e.g. an empty body, an HTML/text interstitial mislabeled as JSON, or a middleman rewriting the payload.

Common situations: Proxy/CDN intercepting the request and returning an empty or HTML 200 response; captive portals; Jina API contract changes; custom fetch implementations returning stubbed bodies in tests.

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 can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ac911e155488c01f. Report an issue: GitHub.