can1357/oh-my-pi · error · SearchProviderError

Jina API error (${response.status}): ${errorText}

Error message

Jina API error (${response.status}): ${errorText}

What it means

Thrown by callJinaSearch when the Jina Reader search API (s.jina.ai) returns a non-OK HTTP status that classifyProviderHttpError does not classify into a more specific error. The status and response body are embedded in the message and reused as the error status.

Source

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

	requestUrl.searchParams.set("count", String(numResults));

	const headers: Record<string, string> = {
		Accept: "application/json",
		Authorization: `Bearer ${apiKey}`,
	};
	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> {

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the status and body in the message; fix the indicated cause (invalid key, quota, parameters).
  2. Verify the Jina API key at https://jina.ai and re-export JINA_API_KEY / update the provider 'jina' key in AuthStorage.
  3. Check billing/credits on the Jina account if the status is 402/403.
  4. Retry with backoff on 5xx; check Jina's status page for incidents.

Example fix

# before
$ export JINA_API_KEY=jna_old_expired
# after: regenerate key at jina.ai dashboard
$ export JINA_API_KEY=jna_live_current_key
Defensive patterns

Strategy: try-catch

Validate before calling

if (!process.env.JINA_API_KEY?.startsWith('jina_')) console.warn('JINA_API_KEY looks missing or malformed');

Type guard

function isJinaHttpError(e: unknown): e is SearchProviderError {
  return e instanceof SearchProviderError && e.provider === 'jina' && typeof e.statusCode === 'number';
}

Try / catch

try {
  return await search({ provider: 'jina', query });
} catch (err) {
  if (isJinaHttpError(err)) {
    if (err.statusCode === 401 || err.statusCode === 402) refreshJinaKeyAndBilling();
    else if (err.statusCode && err.statusCode >= 500) return retryWithBackoff();
  }
  throw err;
}

Prevention

When it happens

Trigger: GET {JINA_SEARCH_URL}/{query}?count=N with Bearer auth returns non-2xx — e.g. 401/403 invalid or revoked Jina API key, 402 out of credits, 404 malformed query URL, 422/400 bad parameters, 5xx Jina outages — in forms the classifier does not match.

Common situations: Expired or typo'd JINA_API_KEY; free-tier quota exhausted (payment required); team billing issues; Jina API deprecations or temporary outages.

Related errors


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