Skip to content

openai-compatible adapter sends max_tokens to GPT-5/o-series reasoning models that require max_completion_tokens #25096

Closed as not planned

Description

@bmeindl

Summary

The bundled @ai-sdk/openai-compatible provider hardcodes max_tokens in chat-completions requests. OpenAI's reasoning-model family (GPT-5.x, o1, o3, o4) rejects this and demands max_completion_tokens instead. Result: any reasoning model behind an OpenAI-compatible proxy returns 503 BadRequest from the upstream API, but opencode swallows the error and the user sees a silent timeout / hung session.

Environment

  • opencode 1.14.30 (curl install, macOS)
  • Provider: OpenAI-compatible proxy (in our case "IU Unified Endpoint" exposing /openai/v1)
  • Affected models tested: gpt-5-nano, gpt-5.4-mini, gpt-5.5, gpt-5.5-pro

Reproduce

~/.config/opencode/opencode.json:

{
  "provider": {
    "p": {
      "npm": "@ai-sdk/openai-compatible",
      "options": {
        "baseURL": "https://your-openai-compatible-proxy/openai/v1",
        "apiKey": "{env:API_KEY}"
      },
      "models": { "gpt-5.4-mini": {"name": "GPT-5.4 mini"} }
    }
  }
}

Run:

echo "Say HELLO" | opencode run --model p/gpt-5.4-mini --dangerously-skip-permissions

Result: hangs, no output. With --print-logs --log-level INFO you can see:

ERROR ... AI_APICallError ... statusCode=503 ...
"responseBody":"... Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead."

Workaround

Use the native @ai-sdk/openai adapter (which knows the reasoning-model param convention) instead of openai-compatible:

"p": {
  "npm": "@ai-sdk/openai",
  "options": {
    "baseURL": "https://your-openai-compatible-proxy/openai/v1",
    "apiKey": "{env:API_KEY}"
  },
  ...
}

This works perfectly for the same proxy + same models. So the proxy itself is fine; the problem is purely in how openai-compatible builds the request body.

Suggested fix

Two options:

  1. Auto-detect reasoning models in openai-compatible by model-id prefix (gpt-5*, o1*, o3*, o4*) and switch the param to max_completion_tokens. Brittle but matches what @ai-sdk/openai already does.

  2. Expose a per-provider config flag like "reasoning_models": ["gpt-5*"] or "max_tokens_param": "max_completion_tokens" so users can configure the proxy explicitly.

Option 1 is more "just works" for users; option 2 is more explicit. Maybe both — auto-detect with override.

Why this matters

Many corporate / EU proxies expose OpenAI's reasoning models through an openai-compatible gateway. As more providers ship reasoning-only models, this will affect more users. The silent-timeout failure mode is also rough: users have no idea why their agent is hanging until they enable debug logs.

Related

Happy to PR if there's preference on option 1 vs 2.

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 30, 2026
  2. github-actions commented on Apr 30, 2026

    @github-actions
    Contributor

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

    You may want to add a comment or upvote on those issues rather than tracking this separately, unless there is a specific aspect (e.g., the silent-timeout failure mode for openai-compatible proxies) that is not covered there.

  3. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  4. Erickrus commented on May 28, 2026

    @Erickrus

    You can use plugin to patch the output

    .opencode/
      plugin/
        openai-compatible-fix.js

    The script looks like this, fixed both reasoningSummary and max_completion_tokens

    export const OpenAICompatibleFix = async(client) => {
      return {
        "chat.params": async (incoming, output) => {
          // only patch for these models
          const allowedModels = new Set(["gpt-5.1","o1","o3"]);
          if (!allowedModels.has(incoming.model.name)) return;
          try {
          } catch(err) {
            delete output.options.reasoningSummary;
            output.options.max_completion_tokens = output.maxOutputTokens;
            output.options.max_tokens = undefined;
          }
        },
      };
    };
  5. github-actions commented on Jul 27, 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.

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