CherryHQ/cherry-studio · error · Error
Rerank response results must contain numeric index and relev
Error message
Rerank response results must contain numeric index and relevance_score
What it means
Thrown by downloadAndPersistImageUrls() when the remote generation succeeded and returned one or more URLs, but every single download+persistence attempt failed (files.length === 0). Each URL is fetched, base64-encoded, and turned into an internal file_entry via fileManager.createInternalEntry; if none survive, the job fails to avoid reporting a paid generation as an empty success. A partial failure (some succeeded) does NOT throw — it logs a warning and returns what it has.
Source
Thrown at packages/ai-sdk-provider/src/openai-compatible-reranking-model.ts:97
body: rawValue
}
}
}
}
function parseRerankResponse(body: unknown, documentCount: number): RerankRanking {
const results = (body as OpenAICompatibleRerankResponse).results
if (!Array.isArray(results)) {
throw new Error('Rerank response must contain a results array')
}
return results.map((result) => {
if (typeof result !== 'object' || result === null) {
throw new Error('Rerank response results must be objects')
}
if (typeof result.index !== 'number' || typeof result.relevance_score !== 'number') {
throw new Error('Rerank response results must contain numeric index and relevance_score')
}
if (!Number.isInteger(result.index) || result.index < 0 || result.index >= documentCount) {
throw new Error('Rerank response results must reference a valid document index')
}
return { index: result.index, relevanceScore: result.relevance_score }
})
}
export function createOpenAICompatibleRerankingModel(
modelId: string,
settings: OpenAICompatibleRerankingModelSettings
): RerankingModelV3 {
const baseURL = withoutTrailingSlash(settings.baseURL)
if (!baseURL) {
throw new Error('OpenAI-compatible reranking model requires baseURL')
}View on GitHub (pinned to 726446b54c)
Solutions
- Check host network egress to the image URLs' hostnames and TLS/proxy settings in the main process.
- Verify free disk space and write permissions on the userData/file_entry storage location.
- If URLs expire, download sooner (reduce work between poll completion and download) or request longer-lived URLs via providerOptions if the vendor supports it.
- Retry the job once after a transient CDN/network blip — a single retry is cheap since the failure was post-generation (note: job retry is capped at 1 attempt by defaultRetryPolicy, so re-enqueue from the UI).
- Inspect the warn logs for individual download errors to see whether it was a network failure, a parse failure, or a persistence failure.
Example fix
// before: downloads happen with no per-URL diagnostics on total failure
for (const url of urls) {
const downloaded = await downloadImageAsBase64(url, signal)
files.push(await fileManager.createInternalEntry({ source: 'base64', data: toDataUrl(downloaded), cleanupPolicy }))
}
// after: capture per-URL failure reasons so the thrown error is diagnosable
const failures: string[] = []
for (const url of urls) {
try {
const downloaded = await downloadImageAsBase64(url, signal)
files.push(await fileManager.createInternalEntry({ source: 'base64', data: toDataUrl(downloaded), cleanupPolicy }))
} catch (e) { failures.push(`${url}: ${e instanceof Error ? e.message : String(e)}`) }
}
if (files.length === 0) throw new Error(`Image generation produced ${urls.length} URL(s) but all downloads failed [${failures.join('; ')}]`) Defensive patterns
Strategy: retry
Validate before calling
// Best-effort preflight that the host can reach the vendor CDN host
// before paying for generation (cheap HEAD/GET to the image host root).
async function canReachCdn(host: string): Promise<boolean> {
try { await fetch(`https://${host}/`, { method: 'HEAD' }); return true }
catch { return false }
} Try / catch
try {
await generateImageViaJob(payload)
} catch (e) {
if (e instanceof Error && /all downloads failed/.test(e.message)) {
// post-generation failure: a single re-enqueue is cheap and often recovers a transient CDN blip
await retryGenerateImageViaJob(payload)
} else throw e
} Prevention
- Whitelist the vendor image-CDN hostnames in the main process network egress rules.
- Monitor free disk space on the userData volume where file_entry blobs are written.
- Download URLs immediately after poll completes to avoid signed-URL expiry windows.
When it happens
Trigger: All returned image URLs are expired/revoked by the time download runs (short-lived signed URLs); the host cannot reach the vendor's CDN/edge due to firewall or DNS; disk full or the file_entry store is unwritable so every createInternalEntry rejects; a proxy intercepts and blocks the image hosts; the media_type/data parsing throws for every entry.
Common situations: Network egress restrictions in a containerized/sandboxed main process blocking the image CDN; a long poll delay causing signed URLs to expire before download; disk pressure on the userData volume; corporate proxy certificate rejection on the image host; vendor CDN regional outage.
Related errors
- Failed to upload image to WeChat CDN
- ModelScope API error: ${response.status} - ${errorText}
- ModelScope API request timeout after ${timeout / 1000}s
- errorData.error?.message || 'Image generation failed'
- PPIO API error: ${response.status} - ${errorText}
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/ec2e3528efe0da40.
Report an issue: GitHub.