ai-openrouter: unconditional `stream_options.include_usage` injection breaks `provider.require_parameters: true`
@AlemTuzlak is already working on this.
Since Aug 21, 2026.
- 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.5 — require_parameters: false works, true 404s every call).
Injection sites (current main):
-
packages/ai-openrouter/src/adapters/text.ts—chatStream:streamOptions: { ...(chatRequest.streamOptions ?? {}), includeUsage: true, // hardcoded after the spread — caller cannot disable }, -
same file,
structuredOutputStream— strips the caller'sstreamOptionsthen re-adds a hardcodedstreamOptions: { 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:
- Respect an explicit caller value:
modelOptions.streamOptions.includeUsage: false(orstreamOptions: null) suppresses the injection, or - an adapter-level option to disable usage-tracking injection, or
- the OpenRouter adapter omits
stream_optionswhen the request carriesprovider.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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.