{"record":{"id":"ef1854cf5a60407d","repo":"can1357/oh-my-pi","slug":"jina-api-error-response-status-errortext","errorCode":null,"errorMessage":"Jina API error (${response.status}): ${errorText}","messagePattern":"Jina API error \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"SearchProviderError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/web/search/providers/jina.ts","lineNumber":77,"sourceCode":"\trequestUrl.searchParams.set(\"count\", String(numResults));\n\n\tconst headers: Record<string, string> = {\n\t\tAccept: \"application/json\",\n\t\tAuthorization: `Bearer ${apiKey}`,\n\t};\n\tif (site) headers[\"X-Site\"] = site;\n\theaders[\"X-Respond-With\"] = \"no-content\";\n\theaders[\"X-Retain-Images\"] = \"none\";\n\tconst response = await fetchImpl(requestUrl, {\n\t\theaders,\n\t\tsignal: withHardTimeout(signal, timeoutMs),\n\t});\n\n\tif (!response.ok) {\n\t\tconst errorText = await response.text();\n\t\tconst classified = classifyProviderHttpError(\"jina\", response.status, errorText);\n\t\tif (classified) throw classified;\n\t\tthrow new SearchProviderError(\"jina\", `Jina API error (${response.status}): ${errorText}`, response.status);\n\t}\n\n\tconst payload = (await response.json()) as JinaSearchEnvelope | JinaSearchResponse | null;\n\tif (Array.isArray(payload)) return payload;\n\tif (!payload || typeof payload !== \"object\") {\n\t\tthrow new SearchProviderError(\"jina\", \"Jina API returned invalid response: expected an object or array\");\n\t}\n\tif (typeof payload.code === \"number\" && payload.code !== 200) {\n\t\tthrow new SearchProviderError(\"jina\", `Jina API response reported failure (${payload.code})`, payload.code);\n\t}\n\tif (!Array.isArray(payload.data)) {\n\t\tthrow new SearchProviderError(\"jina\", \"Jina API returned invalid response: expected data array\");\n\t}\n\treturn payload.data as JinaSearchResponse;\n}\n\n/** Execute Jina web search. */\nexport async function searchJina(params: JinaSearchParams): Promise<SearchResponse> {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/web/search/providers/jina.ts#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"Expired or typo'd JINA_API_KEY; free-tier quota exhausted (payment required); team billing issues; Jina API deprecations or temporary outages.","solutions":["Read the status and body in the message; fix the indicated cause (invalid key, quota, parameters).","Verify the Jina API key at https://jina.ai and re-export JINA_API_KEY / update the provider 'jina' key in AuthStorage.","Check billing/credits on the Jina account if the status is 402/403.","Retry with backoff on 5xx; check Jina's status page for incidents."],"exampleFix":"# before\n$ export JINA_API_KEY=jna_old_expired\n# after: regenerate key at jina.ai dashboard\n$ export JINA_API_KEY=jna_live_current_key","handlingStrategy":"try-catch","validationCode":"if (!process.env.JINA_API_KEY?.startsWith('jina_')) console.warn('JINA_API_KEY looks missing or malformed');","typeGuard":"function isJinaHttpError(e: unknown): e is SearchProviderError {\n  return e instanceof SearchProviderError && e.provider === 'jina' && typeof e.statusCode === 'number';\n}","tryCatchPattern":"try {\n  return await search({ provider: 'jina', query });\n} catch (err) {\n  if (isJinaHttpError(err)) {\n    if (err.statusCode === 401 || err.statusCode === 402) refreshJinaKeyAndBilling();\n    else if (err.statusCode && err.statusCode >= 500) return retryWithBackoff();\n  }\n  throw err;\n}","preventionTips":["Keep the Jina API key current; rotate before expiry.","Monitor credits/billing on the Jina account (402 = out of credits).","Handle 429 with exponential backoff within your rate budget.","Check Jina's status page when 5xx clusters appear."],"tags":["network","http","api-key","jina","search-provider"],"backgroundTag":"jina-api-http-error","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}