TanStack / TanStack/ai

ai-openrouter: unconditional `stream_options.include_usage` injection breaks `provider.require_parameters: true`

Open
#1,037 1 comment 0 reactions 1 assignee View on GitHub

@AlemTuzlak is already working on this.

Since Aug 21, 2026.

has-pr waiting-on: maintainer
Dominant language
TypeScript
Stars
3.1k
Forks
331
Avg merge
1d 22h
Merged PRs (30d)
160

Description

Which project does this relate to?

AI

Describe the bug

@tanstack/ai-openrouter unconditionally injects streamOptions: { includeUsage: true } into every streaming request (serialized to stream_options on the wire by @openrouter/sdk). Because it is hardcoded after the spread of the caller's streamOptions, there is no way to remove or override it via modelOptions.

This breaks OpenRouter's provider routing option provider: { require_parameters: true }: OpenRouter filters to endpoints that declare support for every parameter in the request, and stream_options is an OpenAI Chat-Completions-shaped parameter that e.g. Anthropic-family endpoints do not declare. Result: every streaming call to such providers fails with 404 No endpoints found that can handle the requested parameters (verified live A/B 2026-07-31 with anthropic/claude-sonnet-4.5require_parameters: false works, true 404s every call).

Injection sites (current main):

  • packages/ai-openrouter/src/adapters/text.tschatStream:

    streamOptions: {
      ...(chatRequest.streamOptions ?? {}),
      includeUsage: true,   // hardcoded after the spread — caller cannot disable
    },
    
  • same file, structuredOutputStream — strips the caller's streamOptions then re-adds a hardcoded streamOptions: { includeUsage: true }.

  • same pattern in packages/openai-base/src/adapters/chat-completions-text.ts (stream_options: { include_usage: true }), affecting any OpenAI-compatible gateway that routes to heterogeneous providers.

Expected behavior

One of:

  1. Respect an explicit caller value: modelOptions.streamOptions.includeUsage: false (or streamOptions: null) suppresses the injection, or
  2. an adapter-level option to disable usage-tracking injection, or
  3. the OpenRouter adapter omits stream_options when the request carries provider.require_parameters: true.

Usage accounting is valuable as a default, but it currently costs the ability to use require_parameters: true at all — which is OpenRouter's recommended guard against silent provider-side parameter dropping (e.g. tool schemas).

Steps to reproduce
import { chat } from "@tanstack/ai"
import { openRouterText } from "@tanstack/ai-openrouter"

const stream = chat({
  adapter: openRouterText("anthropic/claude-sonnet-4.5"),
  messages: [{ role: "user", content: "hi" }],
  modelOptions: {
    provider: { only: ["anthropic"], require_parameters: true }
  }
})
for await (const chunk of stream) console.log(chunk.type)
// → RUN_ERROR: 404 "No endpoints found that can handle the requested parameters"
// Flip require_parameters to false → works.

Versions: @tanstack/ai@0.42.0, @tanstack/ai-openrouter@0.15.10 (latest at time of filing); injection sites confirmed still present on main.

Workaround we ship today: require_parameters: false and re-test on every adapter upgrade.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.