Description
rerank() maps every provider-returned ranking[i].index straight back onto the
input documents array with a bare documents[index] lookup, and never validates
the index. The public result contract is non-optional:
// RerankResult<VALUE>
ranking: Array<{ originalIndex: number; score: number; document: VALUE }>;
rerankedDocuments: Array<VALUE>;
@ai-sdk/provider documents RerankingModelV4Result.ranking[].index as "the index
of the document in the original list of documents before reranking".
When a reranking model returns an index that is out of range or non-integer,
rerank() resolves successfully with document: undefined in ranking and
undefined entries in rerankedDocuments — no error, no retry, and the onEnd /
telemetry end event fires as if the call succeeded. The undefined then tends to
surface later as a TypeError far from the cause.
This is the same shape as #20355 (embed() resolves with an undefined embedding)
and #20351 (empty choices[]): a structurally valid but semantically invalid
successful provider response passed through as a value that violates the SDK's own
result type.
Actual behavior
documents = ['a', 'b', 'c'], one ranking entry, default maxRetries:
provider index |
outcome |
ranking[0].document |
rerankedDocuments |
doRerank calls |
onEnd fired |
3 (=== length) |
resolves |
undefined |
[undefined] |
1 |
yes |
-1 |
resolves |
undefined |
[undefined] |
1 |
yes |
5 (> length) |
resolves |
undefined |
[undefined] |
1 |
yes |
1.5 |
resolves |
undefined |
[undefined] |
1 |
yes |
The malformed response is not retried (the provider is called once), so this is
deterministic rather than a transient failure.
Expected behavior
An invalid provider ranking index should not produce a successful RerankResult
containing undefined documents. Adjacent malformed-successful-response handling
in the same package surfaces this as InvalidResponseDataError
(embed-many.ts validateEmbeddingCount; #20358 / #20362) — but the exact error
type and whether the check belongs inside or outside the retry callback are for
maintainers to decide.
Control (unchanged, valid input)
ranking indices [2, 0] -> rerankedDocuments ['c', 'a']
Valid in-range rankings continue to work as before.
Source pointers (main @ c3c189c068baefe62808b4eca5432fe092dc37cb)
packages/ai/src/rerank/rerank.ts — document: documents[ranking.index] in
both the onEnd event payload and the DefaultRerankResult construction (both
after retry() resolves); no Number.isInteger / 0 <= index < documents.length
check.
packages/ai/src/rerank/rerank-result.ts — ranking[].document: VALUE,
rerankedDocuments: Array<VALUE>.
packages/provider/src/reranking-model/v4/reranking-model-v4-result.ts —
index semantics.
I searched issues, PRs, and recent commits (rerank invalid index,
rerank out of range, rerank undefined document, ranking index validation,
InvalidResponseDataError rerank) and found nothing covering rerank index
validation.
Reproduction
Minimal, using the public API and the shipped mock (ai @ main,
c3c189c068baefe62808b4eca5432fe092dc37cb — current main at the time of
reproduction):
import { rerank } from 'ai';
import { MockRerankingModelV4 } from 'ai/test';
const result = await rerank({
model: new MockRerankingModelV4({
// documents.length === 3, so index 3 is out of range
doRerank: async () => ({ ranking: [{ index: 3, relevanceScore: 0.9 }] }),
}),
documents: ['a', 'b', 'c'],
query: 'q',
});
console.log(result.ranking[0].document); // => undefined
console.log(result.rerankedDocuments); // => [ undefined ]
As a failing test in packages/ai/src/rerank/:
import { expect, it } from 'vitest';
import { MockRerankingModelV4 } from '../test/mock-reranking-model-v4';
import { rerank } from './rerank';
it('does not resolve with an undefined document for an out-of-range index', async () => {
const model = new MockRerankingModelV4({
doRerank: async () => ({ ranking: [{ index: 3, relevanceScore: 0.9 }] }),
});
await expect(
rerank({ model, documents: ['a', 'b', 'c'], query: 'q' }),
).rejects.toThrow();
});
On current main this test fails: rerank() resolves with
DefaultRerankResult { ranking: [{ document: undefined, originalIndex: 3, score: 0.9 }] }.
AI SDK Version
ai: main @ c3c189c068baefe62808b4eca5432fe092dc37cb (also reproduces on published ai@7.0.77)
- Node: v22.13+
Code of Conduct
Description
rerank()maps every provider-returnedranking[i].indexstraight back onto theinput
documentsarray with a baredocuments[index]lookup, and never validatesthe index. The public result contract is non-optional:
@ai-sdk/providerdocumentsRerankingModelV4Result.ranking[].indexas "the indexof the document in the original list of documents before reranking".
When a reranking model returns an index that is out of range or non-integer,
rerank()resolves successfully withdocument: undefinedinrankingandundefinedentries inrerankedDocuments— no error, no retry, and theonEnd/telemetry end event fires as if the call succeeded. The
undefinedthen tends tosurface later as a
TypeErrorfar from the cause.This is the same shape as #20355 (
embed()resolves with anundefinedembedding)and #20351 (empty
choices[]): a structurally valid but semantically invalidsuccessful provider response passed through as a value that violates the SDK's own
result type.
Actual behavior
documents = ['a', 'b', 'c'], one ranking entry, defaultmaxRetries:indexranking[0].documentrerankedDocumentsdoRerankcallsonEndfired3(=== length)undefined[undefined]-1undefined[undefined]5(> length)undefined[undefined]1.5undefined[undefined]The malformed response is not retried (the provider is called once), so this is
deterministic rather than a transient failure.
Expected behavior
An invalid provider ranking index should not produce a successful
RerankResultcontaining
undefineddocuments. Adjacent malformed-successful-response handlingin the same package surfaces this as
InvalidResponseDataError(
embed-many.tsvalidateEmbeddingCount; #20358 / #20362) — but the exact errortype and whether the check belongs inside or outside the retry callback are for
maintainers to decide.
Control (unchanged, valid input)
Valid in-range rankings continue to work as before.
Source pointers (
main@c3c189c068baefe62808b4eca5432fe092dc37cb)packages/ai/src/rerank/rerank.ts—document: documents[ranking.index]inboth the
onEndevent payload and theDefaultRerankResultconstruction (bothafter
retry()resolves); noNumber.isInteger/0 <= index < documents.lengthcheck.
packages/ai/src/rerank/rerank-result.ts—ranking[].document: VALUE,rerankedDocuments: Array<VALUE>.packages/provider/src/reranking-model/v4/reranking-model-v4-result.ts—indexsemantics.I searched issues, PRs, and recent commits (
rerank invalid index,rerank out of range,rerank undefined document,ranking index validation,InvalidResponseDataError rerank) and found nothing covering rerank indexvalidation.
Reproduction
Minimal, using the public API and the shipped mock (
ai@main,c3c189c068baefe62808b4eca5432fe092dc37cb— currentmainat the time ofreproduction):
As a failing test in
packages/ai/src/rerank/:On current
mainthis test fails:rerank()resolves withDefaultRerankResult { ranking: [{ document: undefined, originalIndex: 3, score: 0.9 }] }.AI SDK Version
ai:main@c3c189c068baefe62808b4eca5432fe092dc37cb(also reproduces on publishedai@7.0.77)Code of Conduct