can1357/oh-my-pi · error · SearchProviderError

Jina API returned invalid response: expected data array

Error message

Jina API returned invalid response: expected data array

What it means

Thrown by callJinaSearch when the Jina response parsed as JSON is an object (or after the code check passes) but its `data` field is not an array. The provider's contract with Jina is that successful responses carry results in payload.data; anything else is treated as an uninterpretable response.

Source

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

	});

	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,
		apiKey =>
			callJinaSearch(apiKey, params.query, numResults, params.site, params.signal, params.fetch, params.timeoutMs),
		{
			signal: params.signal,
			missingKeyMessage: 'Jina credentials not found. Set JINA_API_KEY or configure an API key for provider "jina".',
		},

View on GitHub (pinned to 9690622007)

Solutions

  1. Log the raw response body to confirm the actual shape Jina returned
  2. Check for Jina API changelog/version updates and update the JinaSearchResponse type if the schema changed
  3. Check for intercepting proxies or gateways rewriting the response
  4. Report/pin against a known-good Jina endpoint version
Defensive patterns

Strategy: type-guard

Validate before calling

// validate shape defensively before consuming results
const res = await fetch(url); const body = await res.json();
if (body && typeof body === 'object' && Array.isArray(body.data)) { /* safe */ }

Type guard

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

Try / catch

try {
  const res = await searchJina({ query, apiKey });
} catch (err) {
  if (err instanceof SearchProviderError && err.message.includes('expected data array')) {
    logRawResponseForDiagnosis();
    useFallbackProvider();
  } else throw err;
}

Prevention

When it happens

Trigger: Jina returns HTTP 200 with code 200 (or no code field) but `data` is missing, null, an object, or a string — e.g. a schema change on Jina's side or an unexpected empty-body success.

Common situations: Jina API version drift changing the response envelope; proxy/gateway replacing the body; malformed responses on partial outages.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/2bdf5a68009a4af2. Report an issue: GitHub.