openclaw - ✅(Solved) Fix `models.providers.<id>.api` enum mismatch crashes gateway on startup — no recovery without manual config edit [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#72477Fetched 2026-04-27 05:29:56
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
cross-referenced ×2closed ×1

When the models.providers.<id>.api enum values are refined across versions (or when a provider is configured with a value that is later removed from the enum), the gateway enters a crash loop on startup. doctor --fix reinstalls the systemd unit but does not migrate or warn about stale enum values in the config file, leaving the gateway completely down until the user manually edits openclaw.json.

Error Message

When the models.providers.<id>.api enum values are refined across versions (or when a provider is configured with a value that is later removed from the enum), the gateway enters a crash loop on startup. doctor --fix reinstalls the systemd unit but does not migrate or warn about stale enum values in the config file, leaving the gateway completely down until the user manually edits openclaw.json. 2. Fatal abort on validation error: lifecycle-core calls getConfigValidationError() on both start and restart. Any config error (including enum mismatch) triggers fail(), aborting the gateway entirely.

2. Invalid provider api should be a warning, not a fatal error — scoped narrowly

Root Cause

Root Cause (Codebase Verification)

Fix Action

Fixed

PR fix notes

PR #72492: fix(doctor): auto-migrate stale provider api enum values

Description (problem / solution / changelog)

Problem

When the models.providers.<id>.api enum is refined across versions (e.g., "openai""openai-completions" / "openai-responses" / "openai-codex-responses"), existing configs retain stale values that cause a fatal validation error and crash loop on startup.

doctor --fix already has a legacyConfigRules + normalizeCompatibilityConfig migration framework, but was missing a rule for the api enum. See #72477 for full context.

Fix

Adds normalizeLegacyProviderApi() to the existing doctor migration pipeline (legacy-config-compatibility-base.ts), mapping stale "openai""openai-completions" (the most common adapter for OpenAI-compatible proxies like OpenRouter).

Migration table

Old valueNew valueRationale
"openai""openai-completions"Matches Chat Completions endpoint used by OpenRouter and compatible proxies

Note: Users targeting OpenAI Responses API or Codex API would need "openai-responses" or "openai-codex-responses" respectively. The migration logs a change message so users are informed and can manually adjust if needed. Unknown stale values are left untouched for config validation to catch.

Files changed

  • src/commands/doctor/shared/legacy-config-provider-api-migrate.ts — new normalizer that iterates models.providers, checks each api against MODEL_APIS, and replaces known stale values
  • src/commands/doctor/shared/legacy-config-provider-api-migrate.test.ts — unit tests covering: migration of "openai", no-op for valid values, skip for unknown stale values, graceful handling of missing models/providers
  • src/commands/doctor/shared/legacy-config-compatibility-base.ts — wires the new normalizer into the existing pipeline

Design decisions

  • Uses MODEL_APIS from types.models.ts as the source of truth for valid values, not a hardcoded list
  • Follows the same pattern as other normalizers (normalizeLegacyMistralModelMaxTokens, normalizeLegacyBrowserConfig, etc.)
  • Only handles known stale values with deterministic mappings; unknown stale values fall through to config validation (which will produce a clear error message with the list of valid options)

Related

  • #72477

Changed files

  • src/commands/doctor/shared/legacy-config-compatibility-base.ts (modified, +2/-0)
  • src/commands/doctor/shared/legacy-config-provider-api-migrate.test.ts (added, +115/-0)
  • src/commands/doctor/shared/legacy-config-provider-api-migrate.ts (added, +66/-0)

PR #72542: Fix stale model provider API config recovery

Description (problem / solution / changelog)

Summary

  • Migrate legacy models.providers.*.api = "openai" values to openai-completions in doctor/runtime compat.
  • Let gateway startup skip providers with stale provider API enum values instead of aborting boot.

Tests

  • pnpm test src/commands/doctor-legacy-config.migrations.test.ts src/gateway/server-startup-config.recovery.test.ts
  • pnpm check:changed
  • Temp gateway smoke with invalid provider API reached ready after logging the skipped provider.

Fixes #72477

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/commands/doctor-legacy-config.migrations.test.ts (modified, +34/-0)
  • src/commands/doctor/shared/legacy-config-compatibility-base.ts (modified, +2/-0)
  • src/commands/doctor/shared/legacy-config-core-normalizers.ts (modified, +75/-3)
  • src/gateway/server-startup-config.recovery.test.ts (modified, +77/-0)
  • src/gateway/server-startup-config.ts (modified, +120/-6)
  • src/gateway/server.impl.ts (modified, +1/-0)

Code Example

Invalid config:
- models.providers.openrouter.api: Invalid option:
  expected one of "openai-completions"|"openai-responses"|"openai-codex-responses"
  |"anthropic-messages"|"google-generative-ai"|"github-copilot"
  |"bedrock-converse-stream"|"ollama"|"azure-openai-responses"

---

"openai-completions", "openai-responses", "openai-codex-responses",
   "anthropic-messages", "google-generative-ai", "github-copilot",
   "bedrock-converse-stream", "ollama", "azure-openai-responses"

---

const configError = await getConfigValidationError();
if (configError) {
  fail(`config is invalid.\n${configError}\nFix the config and retry, or run "openclaw doctor" to repair.`);
  return;
}
RAW_BUFFERClick to expand / collapse

title: "models.providers.<id>.api enum mismatch crashes gateway on startup — no recovery without manual config edit" labels: bug

Summary

When the models.providers.<id>.api enum values are refined across versions (or when a provider is configured with a value that is later removed from the enum), the gateway enters a crash loop on startup. doctor --fix reinstalls the systemd unit but does not migrate or warn about stale enum values in the config file, leaving the gateway completely down until the user manually edits openclaw.json.

Context

OpenRouter (and similar OpenAI-compatible proxies) use https://openrouter.ai/api/v1/chat/completions, which is an OpenAI Chat Completions-compatible endpoint. It is intuitive — and was apparently valid at some point — to configure api: "openai" for such providers. After the api enum was refined into openai-completions / openai-responses / openai-codex-responses, the bare "openai" value became invalid, causing the following failure:

Invalid config:
- models.providers.openrouter.api: Invalid option:
  expected one of "openai-completions"|"openai-responses"|"openai-codex-responses"
  |"anthropic-messages"|"google-generative-ai"|"github-copilot"
  |"bedrock-converse-stream"|"ollama"|"azure-openai-responses"

Note: I was not able to determine the exact version where "openai" was a valid api value. It may have been valid in an earlier release, or it may have been set by the onboarding flow / user intuition. Either way, the resilience problem is the same — see proposals below.

Reproduction

  1. Have openclaw.json with models.providers.openrouter.api = "openai"
  2. Upgrade openclaw to a version where the enum no longer includes "openai"
  3. systemctl --user restart openclaw-gateway.service
  4. Gateway crashes on every start with Invalid configMain process exited, code=exited, status=1/FAILURE → restart loop

Impact

  • Gateway completely down until manual config edit
  • doctor --fix does not resolve (it fixes the unit, not the config value)
  • No degradation path — a single stale enum value kills the entire service
  • A user encountering this after an upgrade has no guided path to recovery

Root Cause (Codebase Verification)

Verified against v2026.4.24:

  1. The api enum is defined in runtime-schema as:

    "openai-completions", "openai-responses", "openai-codex-responses",
    "anthropic-messages", "google-generative-ai", "github-copilot",
    "bedrock-converse-stream", "ollama", "azure-openai-responses"
  2. Fatal abort on validation error: lifecycle-core calls getConfigValidationError() on both start and restart. Any config error (including enum mismatch) triggers fail(), aborting the gateway entirely.

  3. No migration for api enum: doctor --fix has a legacyConfigRules + normalizeCompatibilityConfig framework that migrates other stale config keys (e.g., threadBindings.ttlHours→idleHours, sandbox.perSession→scope), but has no rule for models.providers.<id>.api.

Proposed Fix (two parts)

1. doctor --fix should auto-migrate stale api enum values

The existing legacyConfigRules framework can accommodate a new migration rule. Suggested mapping:

Old valueNew valueRationale
"openai""openai-completions"Most common adapter; matches Chat Completions endpoint used by OpenRouter and compatible proxies

Caveat: Users targeting OpenAI's Responses API or Codex API would need "openai-responses" or "openai-codex-responses" respectively. The migration could emit a warning when replacing "openai", prompting the user to verify the correct adapter if they need a non-default variant.

If no deterministic mapping exists, fall back to a warning + prompt.

2. Invalid provider api should be a warning, not a fatal error — scoped narrowly

Proposed scope: Only downgrade models.providers.<id>.api enum mismatches from fatal to warning. Other validation errors (missing required fields, type mismatches) would remain fatal.

The affected provider would be excluded from the provider registry at runtime (treated as if absent), with a warning logged. This preserves the existing safety model for genuine misconfigurations while handling upgrade-artifact enum drift gracefully.

Current behavior (lifecycle-core):

const configError = await getConfigValidationError();
if (configError) {
  fail(`config is invalid.\n${configError}\nFix the config and retry, or run "openclaw doctor" to repair.`);
  return;
}

Open Questions

  • Was "openai" ever a valid api value? I couldn't verify this from the current codebase alone. If it was never valid, this shifts from a "regression" to a "usability/resilience" issue — but the impact is the same either way.
  • Should other enum mismatches also be non-fatal? I've scoped this proposal narrowly to api only, but there may be other enum fields where the same resilience argument applies.
  • What's the full list of stale values that need migration? Only "openai""openai-completions" is known; there may be others from older versions.

Environment

  • OpenClaw version: 2026.4.24
  • OS: WSL2 (Ubuntu)
  • Install method: npm global

extent analysis

TL;DR

To fix the gateway crash caused by an api enum mismatch, update the models.providers.<id>.api value in openclaw.json to a valid enum value, such as "openai-completions", and consider implementing a migration rule in doctor --fix to handle stale enum values.

Guidance

  • Verify the api enum value in openclaw.json and update it to a valid value if necessary.
  • Consider adding a migration rule to doctor --fix to handle stale api enum values, such as mapping "openai" to "openai-completions".
  • To prevent fatal errors, modify the lifecycle-core code to downgrade models.providers.<id>.api enum mismatches from fatal to warning, excluding the affected provider from the provider registry at runtime.
  • Test the changes to ensure the gateway starts successfully and the provider is properly configured.

Example

// Proposed migration rule in doctor --fix
const legacyConfigRules = {
  // ...
  'models.providers.<id>.api': (value) => {
    if (value === 'openai') {
      return 'openai-completions';
    }
    // ...
  },
};

Notes

  • The exact version where "openai" was a valid api value is unknown, but the resilience problem remains the same.
  • Other enum fields may also require non-fatal error handling, but this proposal is scoped to api only.
  • The full list of stale values that need migration is unknown and requires further investigation.

Recommendation

Apply the proposed workaround by updating the api enum value in openclaw.json and consider implementing a migration rule in doctor --fix to handle stale enum values, as this will prevent the gateway from crashing due to enum mismatches.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix `models.providers.<id>.api` enum mismatch crashes gateway on startup — no recovery without manual config edit [2 pull requests, 1 participants]