Support credential-level or per-model disable-image-generation for codex-api-key (Azure OpenAI rejects image_generation)

Author: sususu98Created Sep 16, 2026Updated Sep 16, 2026
Labelspending

Is it a request payload issue? [x] Yes, this is a request payload issue. I am using a client/cURL to send a request payload, but I received an unexpected error. [ ] No, it's another issue.

If it's a request payload issue, you MUST know Detailed upstream request and error log attached below.

Describe the bug In the Codex executor (internal/runtime/executor/codex_executor_execute.go:65 and codex_executor_stream.go:74), ensureImageGenerationTool automatically injects {"type": "image_generation", "output_format": "png"} into the upstream request's tools array whenever disable-image-generation is at its default (false / Off):

if e.cfg == nil || e.cfg.DisableImageGeneration == config.DisableImageGenerationOff {
    body = ensureImageGenerationTool(body, baseModel, auth, opts.Headers)
}

When routing models via codex-api-key backed by Azure OpenAI Responses endpoints (e.g. gpt-6-astra or custom models on Azure/NewAPI), Azure OpenAI strictly requires the x-ms-oai-image-generation-deployment header whenever an image_generation tool is present. Because normal chat/completion calls do not provide this header, Azure rejects the request with:

HTTP 400 Bad Request
{
  "type": "error",
  "error": {
    "type": "image_generation_user_error",
    "message": "imagegen deployment must be provided through header: x-ms-oai-image-generation-deployment"
  }
}

Why existing knobs are insufficient in mixed instances

  1. disable-image-generation is process-global (false | true | chat | passthrough). Setting disable-image-generation: chat disables injection for all accounts process-wide, which breaks instances where official Codex OAuth credentials need CPA to inject the hosted image tool.
  2. payload.filter cannot solve this because ensureImageGenerationTool is called after helps.ApplyPayloadConfigWithRequest. Even if a user attempts to strip tools via payload config rules, CPA re-injects the tool right after.
  3. codex-api-key entries (CodexKey) do not currently support credential-level or model-level disable-image-generation.

CLI Type codex / codex-api-key

Model Name azure/gpt-6-astra (or any Azure OpenAI Responses model using codex-api-key)

LLM Client cURL / Claude Code / OpenAI SDK

Request Information Upstream request body generated by CPA:

{
  "model": "gpt-6-astra",
  "instructions": "",
  "input": [{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "Hi"}]}],
  "parallel_tool_calls": true,
  "reasoning": {"effort": "medium"},
  "stream": true,
  "store": false,
  "include": ["reasoning.encrypted_content"],
  "tools": [{"type": "image_generation", "output_format": "png"}]
}

Upstream response:

HTTP 400 Bad Request
{"type":"error","error":{"type":"image_generation_user_error","message":"imagegen deployment must be provided through header: x-ms-oai-image-generation-deployment"}}

Expected behavior Support disabling image_generation injection per codex-api-key credential or per model, for instance:

codex-api-key:
  - api-key: "sk-..."
    base-url: "https://azure-endpoint.openai.azure.com/openai/v1"
    disable-image-generation: chat # or boolean / per-model flag
    models:
      - name: "gpt-6-astra"

Or allow payload.filter rules to be respected without being overridden by subsequent ensureImageGenerationTool injection.

Related Issues

  • #5067 (Codex executor injects image_generation into non-official models like muse-spark; process-global flag is too coarse in mixed setups)

OS Type

  • OS: Linux / Container
  • Version: v7.2.149 / v7.3.4

Source: router-for-me/CLIProxyAPI