CherryHQ/cherry-studio · error · Error
OpenAI-compatible reranking model requires baseURL
Error message
OpenAI-compatible reranking model requires baseURL
What it means
Final fallback in the Vertex listing throwOnError path, reached only when a publisher group is null (failed) but `firstPublisherError` is still `undefined`. Normally every null group records its error in the catch, so this branch is a defensive guard against a logic gap where a group became null without setting the error variable. It exists so throwOnError can never silently pass a partial failure; it never carries the real cause.
Source
Thrown at packages/ai-sdk-provider/src/openai-compatible-reranking-model.ts:114
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')
}
return new OpenAICompatibleRerankingModel(modelId, {
provider: `${settings.name}.rerank`,
url: ({ path }) => {
const url = new URL(`${baseURL}${path}`)
if (settings.queryParams) {
url.search = new URLSearchParams(settings.queryParams).toString()
}
return url.toString()
},
headers: () => ({
...(settings.apiKey ? { Authorization: `Bearer ${settings.apiKey}` } : {}),
...settings.headers
}),
fetch: settings.fetch
})
}View on GitHub (pinned to 726446b54c)
Solutions
- Treat this error as a bug report: it means a publisher group failed without recording its cause — inspect the vertexFetcher implementation for a null-returning path outside the try/catch.
- Temporarily run listing without throwOnError and watch the warn logs; if a publisher still shows no models and no error log, that is the path missing the firstPublisherError assignment.
- Ensure any new null-returning branch in the per-publisher loop assigns firstPublisherError before returning null.
- File/fix an issue in the listModels vertexFetcher so every null result carries a recorded error.
Example fix
// before: a branch returns null without recording the error
const group = await (async () => {
if (!shouldFetch(publisher)) return null // firstPublisherError never set -> fallback message
return await fetchPublisher(publisher)
})()
// after: record the reason before returning null
if (!shouldFetch(publisher)) {
if (firstPublisherError === undefined) firstPublisherError = new Error(`publisher ${publisher} skipped`)
return null
} Defensive patterns
Strategy: validation
Validate before calling
// Defensive: before throwing throwOnError, ensure a cause was recorded.
// (This guard belongs in vertexFetcher internals, not at call sites.)
if (options?.throwOnError && publisherModelGroups.some(g => g === null) && firstPublisherError === undefined) {
firstPublisherError = new Error('publisher group failed without a recorded cause (internal bug)')
} Try / catch
try {
await listModels(provider, signal, { throwOnError: true })
} catch (e) {
if (e instanceof Error && /One or more Vertex AI publisher requests failed/.test(e.message)) {
// invariant gap — report as a bug, then degrade to non-strict listing
reportBug('vertexFetcher returned a null group without recording firstPublisherError')
await listModels(provider, signal)
} else throw e
} Prevention
- In vertexFetcher, ensure every null-returning branch assigns firstPublisherError first.
- Add a test that force-fails one publisher and asserts the thrown error carries the original cause, not the fallback message.
- Code-review null returns in the per-publisher map to confirm they all pass through the try/catch.
When it happens
Trigger: A code path inside the per-publisher map returns null without going through the catch (e.g. an early `return null` added outside the try, or a Promise.all rejection path that bypasses the per-publisher try/catch). In practice this is an internal invariant violation, not an operator-triggerable condition.
Common situations: A future refactor of vertexFetcher that adds a null-returning branch outside the try/catch; an await on a helper that rejects in a way Promise.all surfaces as a rejected group rather than a caught null. Should not occur in normal operation with valid/invalid auth.
Related errors
- Rerank response results must reference a valid document inde
- Provider extension "${id}" not found. Did you forget to regi
- read_file returned an unexpected output type
- Failed to fetch ${url}: Unknown error
- VertexAI requires iam-gcp auth configuration.
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/ae3890a00f7ee35c.
Report an issue: GitHub.