Skip to content

Codex app-server rejects stale serviceTier "priority", and startup warmup misses async model resolution #64815

Description

@sunnydongbo

Summary

I hit two related issues while testing the bundled Codex provider / app-server path in OpenClaw 2026.4.10 / source checkout 850182b502ccd35caf52d6313113e03fc5521d99.

  1. A stale serviceTier: "priority" value can still make it through the OpenClaw Codex bridge, even though the Codex app-server only accepts "fast" | "flex".
  2. Gateway startup warmup can emit a false warning for codex/gpt-5.4 because it only uses static resolveModel(...) and does not fall back to resolveModelAsync(...).

User-visible symptoms

1) Codex app-server request failure

The Codex path can fail with errors like:

  • CodexAppServerRpcError -32600
  • unknown variant 'priority'

This happens when plugins.entries.codex.config.appServer.serviceTier = "priority" is present.

2) False-negative startup warning

Gateway startup can warn with:

  • startup model warmup failed for codex/gpt-5.4

Even when the model is actually resolvable through the async path.

Root cause

serviceTier contract drift

The OpenClaw side still models / forwards serviceTier too loosely in a few places:

  • plugin schema allows arbitrary string
  • runtime config path can forward arbitrary string
  • protocol types still used generic string | null
  • tests still contained stale "priority" fixtures

That lets an invalid value survive until the Codex app-server rejects it.

startup warmup only uses static resolution

prewarmConfiguredPrimaryModel() currently uses static resolveModel(...) only.

For models like codex/gpt-5.4, static resolution can miss even though resolveModelAsync(...) succeeds, which produces a misleading startup warning.

Proposed fix

I validated a minimal source patch locally that does the following:

serviceTier

  • narrow Codex serviceTier handling to "fast" | "flex"
  • sanitize invalid values before forwarding requests to the app-server
  • tighten the bundled plugin schema enum
  • narrow the protocol request types
  • update stale test fixtures
  • add a regression test proving invalid serviceTier is dropped without discarding the rest of the config

startup warmup

  • keep static resolveModel(...) first
  • if static resolution misses, fall back to resolveModelAsync(...)
  • only warn when both resolution paths fail
  • add regression coverage for:
    • static miss + async success
    • static miss + async miss

Files changed in the local fix

  • extensions/codex/openclaw.plugin.json
  • extensions/codex/src/app-server/config.ts
  • extensions/codex/src/app-server/config.test.ts
  • extensions/codex/src/app-server/protocol.ts
  • extensions/codex/src/app-server/run-attempt.test.ts
  • src/gateway/server-startup-post-attach.ts
  • src/gateway/server-startup.test.ts

Validation

pnpm exec vitest run \
  extensions/codex/src/app-server/config.test.ts \
  extensions/codex/src/app-server/run-attempt.test.ts \
  src/gateway/server-startup.test.ts

pnpm codex-app-server:protocol:check

Result:

  • 21 passed
  • protocol check passed

Local fix artifacts

I have a validated local commit and patch for this:

  • local commit: 8953728
  • patch available if useful

Notes

The protocol check required a sibling Codex repo checkout for schema verification:

  • ../codex

In my environment that was:

  • /home/bruce/.openclaw/workspace/_vendor/codex

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions