`app-server` ignores `[features].image_generation = false` and `--disable image_generation` (only `exec` honors them)

Open 💬 2 comments Opened May 9, 2026 by abcjhby2871

Summary

On 0.130.0, codex exec correctly omits the built-in image_generation tool from the /v1/responses request when it is disabled via [features] or --disable image_generation, but codex app-server (which is what the VSCode openai.chatgpt extension launches) keeps emitting {"type":"image_generation"} (and {"type":"web_search"}) in tools[] regardless of either knob. For users on Responses-compatible third-party providers (OneAPI-style proxies, Azure groups without image gen, etc.) this produces an unrecoverable 403 Forbidden: Image generation is not enabled for this group on every turn through the IDE extension while the CLI works fine.

Environment

  • codex-cli: 0.130.0 (npm @openai/codex, bundled linux-x64-musl binary; both report codex-cli 0.130.0)
  • VSCode extension (the IDE plugin launching app-server): openai.chatgpt v26.506.31421 (engines.vscode: ^1.96.2)
  • VSCode: 1.119.0 (commit 8b640eef5a6c6089c029249d48efa5c99adf7d51, x64)
  • OS: Linux x86_64
  • Provider: a third-party OneAPI-compatible deployment, wire_api = "responses"
  • Default chatgpt.cliExecutable: "codex". Spawn observed via ps:

``
codex --disable image_generation app-server --analytics-default-enabled
codex --disable image_generation app-server --listen unix://
``

Reproduction

  1. Configure a custom provider with wire_api = "responses" whose upstream account does not allow image generation (any OneAPI deployment with image gen disabled reproduces this; OpenRouter behaves similarly per #18307).
  2. Set:

``toml
[features]
image_generation = false
`
Confirm:
`
$ codex features list | grep image_generation
image_generation stable false
``

  1. CLI path (works):

``
$ codex exec "hello"
Hello.
`
Captured request:
tools[] does **not** contain image_generation`.

  1. App-server path (broken):
  • Trigger any message from the VSCode extension, OR run codex app-server --analytics-default-enabled and drive it.
  • Whether or not --disable image_generation is on the command line, the captured POST /v1/responses body contains:

``json
"tools": [
…,
{ "type": "web_search" },
{ "type": "image_generation" },

]
``

  • Server returns 403 {"error":{"message":"Image generation is not enabled for this group","type":"permission_error"}}.

Evidence (network capture)

mitmdump in reverse-proxy mode in front of the upstream, with [model_providers.<name>].base_url redirected to the local proxy. Identical session, single user message "hello":

| codepath | tools.length | image_generation in tools[] | result |
|---|---|---|---|
| codex exec | 14 | no | 200 OK |
| codex app-server with [features].image_generation=false | 16 | yes | 403 |
| codex --disable image_generation app-server … | 16 | yes | 403 |

Confirmed via ps -o cmd that --disable image_generation is in fact present on the spawned app-server process; it just doesn't propagate to the Responses tool builder.

Root-cause guess

PR #19442 ("feat: disable capabilities by model provider") routes built-in tool selection for Responses through ProviderCapabilities / ToolCapabilityBounds. The bounds appear to be hard-coded for first-party providers only; user-defined providers fall through to the default "all caps allowed", which silently overrides [features].image_generation = false on the app-server path. PR #20049 only exposes the same bounds to app-server clients; it doesn't extend them to user providers. The CLI --disable flag and [features] setting flow into the session/exec tool builder, not into ToolCapabilityBounds. Net effect: two separate sources of truth for "is this tool allowed", and only one is reachable from user config.

Expected behavior

[features].image_generation = false (or --disable image_generation) should suppress the {"type":"image_generation"} entry from tools[] regardless of subcommand and regardless of whether the provider is a built-in.

Suggested fix (any one of these would unblock)

  1. Have the app-server Responses request builder consult [features] / the --disable set with the same precedence as exec does — or have ToolCapabilityBounds intersect with [features] before the request is built.
  2. Allow user providers to set their own bounds, e.g.:

``toml
[model_providers.example]
disabled_capabilities = ["image_generation", "web_search"]
``
This also addresses #6049 (disable built-in tools) and #18307 (third-party Responses providers rejecting built-ins).

  1. Honor --disable image_generation / --disable web_search on codex app-server directly.

Related

  • #19442 – disable capabilities by model provider (introduced the divergent codepath)
  • #20049 – expose provider capability bounds to app-server clients
  • #6049 – feature request: disable built-in tools for MCP-only execution
  • #18307 – OpenRouter rejects Responses payloads with image_generation/web_search (same class of failure)
  • #19133 – inverse case (image gen unavailable on Azure exec)

Workaround currently used

Local mitmproxy reverse proxy that strips {"type":"image_generation"} (and optionally web_search) from tools[] of POST /v1/responses before forwarding upstream, with [model_providers.<name>].base_url pointed at the local proxy. Works but is not something users should have to deploy.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗