fix(core): Cohere and Voyage rerankers bypass non-positive limit check on NaN topN and send invalid null payload

Geschlossen
#582 3 Kommentare 0 Reaktionen 1 zugewiesene Person Auf GitHub ansehen

Maintainer antworten meist innerhalb von 1 Tag

@bhushan4work arbeitet bereits daran.

Seit 03.11.2026.

  • #589 von @bhushan4work — gemerged

Bewertung

Dieses Issue wurde noch nicht bewertet.

Beschreibung

bug core
Which part?

@chatcops/core

Package version

No response

What happened?
Problem

In both cohereReranker and voyageReranker, candidate reranking enforces the requested limit using:
const limit = Math.floor(topN);
if (chunks.length === 0 || limit <= 0) return [];
If topN evaluates to NaN (such as when parsing unvalidated query/input parameters into retrieval plans), Math.floor(NaN) evaluates to NaN. In JavaScript /
IEEE 754 arithmetic, relational comparisons with NaN (NaN <= 0) always evaluate to false.

Consequently, the early return check is bypassed:

  1. Math.min(limit, chunks.length) calculates Math.min(NaN, chunks.length), which returns NaN.
  2. When serialized for outbound HTTP calls, JSON.stringify converts NaN to null:
    • Cohere receives: {"top_n": null}
    • Voyage receives: {"top_k": null}
  3. Both Cohere and Voyage AI endpoints reject null values with HTTP 400 Bad Request (e.g. invalid request: top_n must be a positive integer), triggering an
    unhandled provider error in postWithRetries that aborts the chat/retrieval turn.
    By contrast, workersAiReranker correctly protects against this:
    const requestedLimit = Number.isFinite(topN) && topN > 0 ? Math.floor(topN) : 0;
    if (!requestedLimit || !chunks.length) return [];
Actual Behavior

• Actual Behavior: Calling rerank(query, chunks, NaN) bypasses the non-positive limit guard, triggers an outbound HTTP request with top_n: null or top_k:
null, and fails with HTTP 400 Bad Request.

Impact

• Any unvalidated or non-numeric topK / topN value passed directly to rerankers or computed via plan() results in an unnecessary outbound API call that fails
with an unhandled HTTP 400 error.
• Causes behavioral inconsistency across @chatcops/core rerankers (workersAiReranker returns [], while cohereReranker and voyageReranker fail with provider
errors).

Acceptance Criteria

• cohereReranker and voyageReranker validate that topN is a positive finite number (e.g., using Number.isFinite(topN) && topN > 0) before making outbound
requests.
• Invoking rerank with NaN or non-finite topN returns [] immediately without sending network requests.
• Test suites in cohere-reranker.test.ts and voyage-reranker.test.ts include assertions for non-finite topN values.

What did you expect?

• Expected Behavior: Calling rerank(query, chunks, NaN) should recognize non-finite / invalid counts, return [] immediately, and avoid making unnecessary
outbound API calls.

How can we reproduce it?
1. Initialize a reranker instance:
    const reranker = cohereReranker({ apiKey: 'dummy-key', fetch: mockFetch });

  2. Call rerank with non-empty chunks and NaN:
    await reranker.rerank('query', [{ id: '1', text: 'chunk' }], NaN);

  3. Inspect mockFetch: instead of returning [] without dispatching a network call (like topN = 0 does), a request is dispatched with body:
    { "model": "rerank-v5.0-pro", "query": "query", "documents": ["chunk"], "top_n": null }
Environment

No response

Vorherrschende Sprache
TypeScript
Sterne
13
Forks
7
Ø Merge
3 Std. 14 Min.
Gemergte PRs (30 T.)
332

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus codercops/chatcops

Alle Issues in codercops/chatcops

Ähnliche Issues

Weitere Issues zu TypeScript

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.