Skip to content

OpenAI-compatible GPT-5.x models still send max_tokens on AI SDK fallback path #40885

Closed as not planned

Description

@ton618to

Description

OpenAI-compatible providers can still send max_tokens for GPT-5-family models on the default AI SDK runtime path. OpenAI-compatible gateways that forward to OpenAI reject these requests with:

Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.

This blocks GPT-5.4 / GPT-5.5 usage through OpenAI-compatible providers even with a minimal opencode configuration and no MCP/tools/plugins enabled.

This looks related to prior max_tokens / max_completion_tokens issues, but the remaining failure path is specifically the default AI SDK fallback path for non-native providers.

Impact

  • Affected: @ai-sdk/openai-compatible providers whose model id is in the GPT-5 family, e.g. gpt-5.4, gpt-5.5.
  • Symptom: upstream 400 from OpenAI-compatible gateway.
  • User-visible result: provider request fails before the model can answer.
  • Severity: high for users routing GPT-5.x through LiteLLM / OpenAI-compatible gateways.

Minimal config shape

Sanitized example:

{
  "$schema": "https://opencode.ai/config.json",
  "model": "proxy/gpt-5.5",
  "provider": {
    "proxy": {
      "npm": "@ai-sdk/openai-compatible",
      "options": {
        "baseURL": "https://example.invalid/v1",
        "apiKey": "REDACTED"
      },
      "models": {
        "gpt-5.5": {
          "name": "GPT-5.5",
          "id": "gpt-5.5",
          "tool_call": true,
          "modalities": { "input": ["text", "image"], "output": ["text"] },
          "limit": { "context": 1050000, "output": 128000 }
        }
      }
    }
  },
  "plugin": [],
  "mcp": {},
  "lsp": {},
  "skills": [],
  "permission": { "*": "deny" }
}

Reproduction

  1. Configure an OpenAI-compatible provider that exposes gpt-5.5 or gpt-5.4.
  2. Disable plugins/MCP/extra tools to rule out tool-count issues.
  3. Start a session using proxy/gpt-5.5.
  4. Send any prompt.

Actual result

The upstream gateway rejects the request:

{
  "error": {
    "code": "unsupported_parameter",
    "message": "Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.",
    "param": "max_tokens",
    "type": "invalid_request_error"
  }
}

Expected result

opencode should not send max_tokens for GPT-5-family models when using an OpenAI-compatible provider that forwards to OpenAI. It should either:

  • use max_completion_tokens, if supported by the provider SDK path, or
  • omit the max-output cap for those models on @ai-sdk/openai-compatible, letting the upstream model default apply.

Root cause hypothesis

The native LLM path can be patched independently, but this bug still appears when opencode falls back to AI SDK for non-native providers.

Relevant runtime path:

  • packages/opencode/src/session/llm.ts logs/selects llm.runtime=ai-sdk for non-native providers.
  • The AI SDK path calls streamText({ maxOutputTokens: prepared.params.maxOutputTokens, ... }).
  • With @ai-sdk/openai-compatible, AI SDK serializes that as max_tokens.
  • OpenAI GPT-5-family models reject max_tokens and require max_completion_tokens.

A local mitigation that fixed the issue was to clear maxOutputTokens during request preparation when:

model.api.npm === "@ai-sdk/openai-compatible"
&& /(?:^|\/)gpt-5(?:[.-]|$)/.test(model.api.id)
&& !model.api.id.includes("gpt-5-chat")

This prevents AI SDK from emitting max_tokens for GPT-5.x OpenAI-compatible routes.

Suggested regression coverage

A regression test can cover request preparation for an OpenAI-compatible gpt-5.5 model and assert:

prepared.params.maxOutputTokens === undefined

This catches the default AI SDK fallback path, which is distinct from native @opencode-ai/llm request body construction.

Privacy note

All provider URLs, API keys, local paths, account names, and logs in this report have been redacted or replaced with generic placeholders.

Activity

  1. github-actions commented on Aug 6, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is distinct from those (e.g. it specifically affects the AI SDK fallback path for non-native providers in a way not covered there), please add a note clarifying what differentiates it.

  2. rekram1-node commented on Aug 6, 2026

    @rekram1-node
    Collaborator

    Need more info, what gateway?
    Symptom: upstream 400 from OpenAI-compatible gateway.

    What provider? Some providers do support this, if your provider doesnt are they expecting max_completion_tokens instead? Or do they not allow this field at all

  3. ton618to commented on Aug 12, 2026

    @ton618to
    Author

    Thanks — the gateway in my repro is LiteLLM exposing an OpenAI-compatible /v1/chat/completions endpoint and forwarding to OpenAI GPT-5.5.

    The upstream rejection is specifically from OpenAI, not a LiteLLM-only validation rule:

    {
      "error": {
        "code": "unsupported_parameter",
        "message": "Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.",
        "param": "max_tokens",
        "type": "invalid_request_error"
      }
    }

    So for this provider path, max_tokens is not allowed. The upstream expects max_completion_tokens.

    The important distinction from #22623 is the runtime path:

    I verified a local mitigation:

    model.api.npm === "@ai-sdk/openai-compatible" &&
    /(?:^|\/)gpt-5(?:[.-]|$)/.test(model.api.id) &&
    !model.api.id.includes("gpt-5-chat")

    For that case, clearing prepared.params.maxOutputTokens prevents AI SDK from emitting max_tokens, and the request no longer fails at admission.

    I also tested the native @opencode-ai/llm OpenAI Chat path separately: it needs to emit max_completion_tokens instead of max_tokens for gpt-5* chat-completions models.

    So the two fixes I validated locally are:

    1. AI SDK fallback / @ai-sdk/openai-compatible: omit maxOutputTokens for GPT-5.x so AI SDK does not send max_tokens.
    2. Native OpenAI Chat route: send max_completion_tokens for GPT-5.x instead of max_tokens.

    Targeted tests I used locally:

    cd packages/opencode && bun test test/provider/transform.test.ts --timeout 30000
    cd packages/llm && bun test test/provider/openai-chat.test.ts --timeout 30000
    

    Both pass with the patch.

  4. github-actions commented on Oct 12, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

  5. rekram1-node commented on Oct 12, 2026

    @rekram1-node
    Collaborator

    Thanks for the detailed writeup and repro. It made this easy to trace.

    This is fixed in OpenCode V2. V2 doesn't use the AI SDK fallback path anymore. Every provider goes through OpenCode's own LLM runtime, and @ai-sdk/openai-compatible maps to the built-in @opencode/ai/providers/openai-compatible package.

    For OpenAI-compatible chat endpoints, V2 now sends max_completion_tokens by default. It only falls back to the legacy max_tokens for providers known to need it, like DeepSeek, Moonshot, Together, Z.ai, Cerebras, NVIDIA and Cloudflare. A LiteLLM proxy in front of GPT-5.x falls under the default, so it should work as-is.

    If a gateway ever needs the other field, you can set it yourself for each model:

    {
      "$schema": "https://opencode.ai/config.json",
      "model": "proxy/gpt-5.5",
      "providers": {
        "proxy": {
          "package": "@opencode/ai/providers/openai-compatible",
          "env": ["PROXY_API_KEY"],
          "settings": { "baseURL": "https://example.invalid/v1" },
          "models": {
            "gpt-5.5": {
              "compatibility": { "maxTokensField": "max_completion_tokens" } // or "max_tokens"
            }
          }
        }
      }
    }

    Your existing V1 config (provider / npm / options) also works unchanged. V2 converts it to the new format in memory without rewriting your file, so you don't have to switch formats to try this.

    Installing V2

    curl -fsSL https://opencode.ai/v2/install | bash
    # or
    brew install anomalyco/tap/opencode-v2
    # or
    npm install -g @opencode/cli

    V1 and V2 both use the opencode command. If you installed V1 with a package manager, uninstall it first. The curl installer replaces the V1 binary on its own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions