{"record":{"id":"cc51f0cd639c7306","repo":"CherryHQ/cherry-studio","slug":"rerank-response-must-contain-a-results-array","errorCode":null,"errorMessage":"Rerank response must contain a results array","messagePattern":"Rerank response must contain a results array","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ai-sdk-provider/src/openai-compatible-reranking-model.ts","lineNumber":88,"sourceCode":"        }\n      },\n      abortSignal,\n      fetch: this.config.fetch\n    })\n\n    return {\n      ranking: value,\n      response: {\n        body: rawValue\n      }\n    }\n  }\n}\n\nfunction parseRerankResponse(body: unknown, documentCount: number): RerankRanking {\n  const results = (body as OpenAICompatibleRerankResponse).results\n  if (!Array.isArray(results)) {\n    throw new Error('Rerank response must contain a results array')\n  }\n\n  return results.map((result) => {\n    if (typeof result !== 'object' || result === null) {\n      throw new Error('Rerank response results must be objects')\n    }\n\n    if (typeof result.index !== 'number' || typeof result.relevance_score !== 'number') {\n      throw new Error('Rerank response results must contain numeric index and relevance_score')\n    }\n\n    if (!Number.isInteger(result.index) || result.index < 0 || result.index >= documentCount) {\n      throw new Error('Rerank response results must reference a valid document index')\n    }\n\n    return { index: result.index, relevanceScore: result.relevance_score }\n  })\n}","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/packages/ai-sdk-provider/src/openai-compatible-reranking-model.ts#L70-L106","documentation":"Thrown after the submit/poll cycle completed successfully but the resulting URL list is empty (covers both submit.imageUrls === [] and poll() === []). Unlike the malformed-submit case (error 400), the provider invocation genuinely finished — it just produced no images. The handler records the invocation with imageCount=0 BEFORE throwing, because the call was observable/billable, then fails to avoid reporting a silent zero-image 'success'. Typical cause is vendor-side content moderation or a degraded response that still charged.","triggerScenarios":"The prompt or input image triggers the vendor's safety/content-moderation filter, which returns a 200 with an empty result array instead of an error; a requested image count of n=0 propagated through; a degraded vendor path that accepts the request but yields no output URLs; an async poll that resolved to an empty array while reporting success.","commonSituations":"Prompt contains disallowed content or copyrighted names; input image is flagged by safety models; vendor temporarily degrades and returns zero results; the n parameter was overridden to 0 somewhere in option mapping; region/account under a content-policy shadow-ban.","solutions":["Revise the prompt to remove content likely to trip the vendor's moderation policy and retry.","Check the vendor dashboard/console for moderation actions or policy flags on the account/model.","Verify the requested image count (n) is >= 1 end-to-end through providerOptions.","Try a different model id from the same provider to isolate whether the block is model-specific.","Inspect the aiUsageRecord for the requestId (`custom-image:<jobId>`) — imageCount=0 with a recorded invocation confirms a vendor-side empty response."],"exampleFix":"// No code fix exists at the caller — the provider genuinely returned nothing.\n// Mitigation is operational: surface a user-facing message and offer retry with a sanitized prompt.\n// before\ntry { await generateImageViaJob(payload) }\ncatch (e) { logger.error(e.message) }\n// after: distinguish the moderation case for the user\ntry { await generateImageViaJob(payload) }\ncatch (e) {\n  if (/completed but returned no image URLs/.test(e.message)) {\n    notifyUser('The model produced no image (possibly content moderation). Try a different prompt.')\n  } else { throw e }\n}","handlingStrategy":"try-catch","validationCode":"// The empty-list case comes from the vendor post-success; you cannot fully\n// prevent it client-side, but you can pre-validate inputs that commonly trip moderation.\nconst MODERATION_RISK = /(violence|explicit|weapon)/i\nif (input.prompt && MODERATION_RISK.test(input.prompt)) {\n  warnUser('Prompt may be filtered by the model content policy.')\n}","typeGuard":null,"tryCatchPattern":"try {\n  await generateImageViaJob(payload)\n} catch (e) {\n  if (e instanceof Error && /completed but returned no image URLs/.test(e.message)) {\n    notifyUser('The model produced no image — likely content moderation. Revise the prompt and retry.')\n  } else throw e\n}","preventionTips":["Sanitize prompts of terms known to trip the vendor's content policy before submitting.","Track the aiUsageRecord (requestId custom-image:<jobId>) to correlate paid-but-empty invocations.","Offer the user a model fallback so a single model's moderation does not block the workflow."],"tags":["image-generation","content-moderation","vendor-api","empty-result"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}