CherryHQ/cherry-studio · error · Error
Rerank response results must be objects
Error message
Rerank response results must be objects
What it means
Thrown inside pollUntilDone() when a transport returned a `taskId` from submit() (signaling async/poll mode) but the same transport does not implement the optional `poll()` method. On the ImageGenerationTransport interface `submit` may return a `taskId` and `poll` is optional — so returning a task id without a poll implementation is an inconsistent adapter contract, not a runtime/config problem. This is a bug in the provider/transport registration, surfaced at the first async submission for that model.
Source
Thrown at packages/ai-sdk-provider/src/openai-compatible-reranking-model.ts:93
return {
ranking: value,
response: {
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 {View on GitHub (pinned to 726446b54c)
Solutions
- Implement `poll(taskId, options)` on the transport object so the returned task id can be resolved to URLs.
- If the model is actually synchronous, do NOT return a taskId from submit() — return imageUrls directly so pollUntilDone is never entered.
- Register the transport through imageTransportRegistry only after both submit and poll (for async) are present.
- Add a unit test that asserts: if submit can return taskId, then transport.poll is a function.
Example fix
// before: async vendor, but poll missing
export const myTransport: ImageGenerationTransport = {
async submit(input) {
const body = await post(url, input)
return { taskId: body.task_id } // poll() never defined
}
}
// after: implement poll to resolve the task
export const myTransport: ImageGenerationTransport = {
async submit(input) {
const body = await post(url, input)
return { taskId: body.task_id }
},
async poll(taskId, { signal }) {
const body = await get(`${url}/${taskId}`, { signal })
if (body.status !== 'SUCCEEDED') throw new Error(`task ${body.status}`)
return body.output.map(o => o.url)
}
} Defensive patterns
Strategy: type-guard
Type guard
// Assert at adapter build time that a transport returning taskId also polls.
function assertPollIfAsync(t: ImageGenerationTransport): void {
// submit can return taskId at runtime; enforce poll presence statically by contract.
if (typeof t.poll !== 'function') {
// mark this transport as sync-only and ensure submit never yields a taskId
console.warn('Transport lacks poll(); submit must return imageUrls only')
}
}
// Stronger: a branded type for async transports
interface AsyncImageTransport extends ImageGenerationTransport { poll: NonNullable<ImageGenerationTransport['poll']> } Try / catch
try {
await generateImageViaJob(payload)
} catch (e) {
if (e instanceof Error && /does not implement polling/.test(e.message)) {
// this is an adapter bug, not a user error — report it, do not retry
reportBug(`Transport for ${modelId} returned a taskId without poll()`)
} else throw e
} Prevention
- When adding a transport, write a unit test: 'if submit returns taskId, transport.poll is a function'.
- Use a typed factory (e.g. createAsyncTransport) that requires both submit and poll, vs createSyncTransport that forbids taskId.
- Review the imageTransportRegistry registration to confirm poll is bound for every async provider.
When it happens
Trigger: A new custom-provider image transport adapter returns `{ taskId }` from submit() (because the vendor is asynchronous) but the developer forgot to implement the `poll` method on the same object; or an existing sync transport was edited to forward a task id from the raw vendor body without adding polling.
Common situations: Adding a new image-generation provider (mirroring ppio/dashscope) and copying the submit shape but omitting poll; refactoring a transport from sync to async and missing the poll method; a transport object built from a partial/factory that conditionally omits poll.
Related errors
- OpenAI-compatible reranking model only supports text documen
- ${provider} returned a task id but does not implement pollin
- Rerank response must contain a results array
- Rerank response results must contain numeric index and relev
- Failed to generate image: ${error.message}
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/8d793c3f84a46458.
Report an issue: GitHub.