openclaw - ✅(Solved) Fix Config validator silently reverts providers.<id> writes with no operator-visible reason (2026.4.25) [1 pull requests, 1 comments, 2 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#73577Fetched 2026-04-29 06:18:00
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Timeline (top)
commented ×1cross-referenced ×1

Adding a providers.<id> block (with apiKey + baseUrl) to ~/.openclaw/openclaw.json causes the gateway to revert to last-known-good on the next reload, with no operator-visible reason. The rejected config is preserved on disk (good), but no log line, doctor check, or CLI output reveals which field/value/schema rule the validator objected to.

Error Message

WARN Config auto-restored from last-known-good: /home/<user>/.openclaw/openclaw.json (reload-invalid-config) WARN {"subsystem":"gateway/reload"} config reload restored last-known-good config after invalid-config No schema error, no JSON path, no field name. Nothing in openclaw doctor output. Nothing additional in journalctl. Anyone trying to wire a custom-baseUrl provider — LiteLLM, a local OpenAI-compat proxy, OpenRouter, an internal mTLS endpoint, etc. — will hit this and have no diagnostic to work from. The error UX makes it look like the config save worked; the operator only finds out by running infer model run and seeing it silently fall back to a different provider/model (the silent-fallback behavior amplifies the impact, but is a separate observation worth its own report). None found. Adding the credential to ~/.openclaw/agents/main/agent/auth-profiles.json resolves the "no API key" error path, but that schema has no slot for baseUrl, so requests still go to the default endpoint (api.anthropic.com for the anthropic provider) and return 401 invalid x-api-key.

Root Cause

Anyone trying to wire a custom-baseUrl provider — LiteLLM, a local OpenAI-compat proxy, OpenRouter, an internal mTLS endpoint, etc. — will hit this and have no diagnostic to work from. The error UX makes it look like the config save worked; the operator only finds out by running infer model run and seeing it silently fall back to a different provider/model (the silent-fallback behavior amplifies the impact, but is a separate observation worth its own report).

Fix Action

Workaround

None found. Adding the credential to ~/.openclaw/agents/main/agent/auth-profiles.json resolves the "no API key" error path, but that schema has no slot for baseUrl, so requests still go to the default endpoint (api.anthropic.com for the anthropic provider) and return 401 invalid x-api-key.

PR fix notes

PR #39766: fix(config): make models.providers.<id>.models optional to allow credential-only entries

Description (problem / solution / changelog)

Problem

When a user configures models.providers.openai with a custom baseUrl (e.g. an OpenAI-compatible embedding endpoint) but without a models array, OpenClaw's config validation rejects the entry with INVALID_CONFIG:

{
  "models": {
    "providers": {
      "openai": {
        "baseUrl": "https://api.gptsapi.net/v1",
        "apiKey": "${OPENAI_API_KEY}",
        "api": "openai-completions"
      }
    }
  }
}

On a live gateway a failed reload is silently ignored (the gateway keeps running with the stale config). The stale config has no models.providers.openai entry, so providerConfig?.baseUrl in resolveRemoteEmbeddingBearerClient is undefined, and the embedding system falls back to the hard-coded DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1" instead of the intended custom endpoint. The user then sees TypeError: fetch failed when the request reaches the wrong host.

Root Cause

ModelProviderSchema in src/config/zod-schema.core.ts declares models as a required field:

models: z.array(ModelDefinitionSchema),  // required — fails if omitted

Users who configure a provider entry solely for credentials/baseUrl (no custom models) have no reason to include an empty models: []. Making the field required creates an unnecessary footgun.

Fix

Change the field declaration to use .default([]):

models: z.array(ModelDefinitionSchema).default([]),

The parsed output still always contains an array (never undefined), so all downstream code that iterates over models remains safe. Configs that omit models now pass validation and the gateway picks up the custom baseUrl correctly.

Tests

src/config/zod-schema.model-provider.test.ts (new file, 3 tests):

  • ✅ Provider entry without models field passes validation and defaults to []
  • ✅ Provider entry with explicit models: [] passes validation
  • baseUrl is preserved when models is omitted

src/memory/embeddings.test.ts (1 test added):

  • createEmbeddingProvider routes to models.providers.openai.baseUrl when no remote.baseUrl override is present

Fixes #39589

Changed files

  • packages/memory-host-sdk/src/host/embeddings.test.ts (modified, +37/-0)
  • src/config/zod-schema.core.ts (modified, +6/-1)
  • src/config/zod-schema.model-provider.test.ts (added, +72/-0)

Code Example

"providers": {
     "anthropic": {
       "apiKey": "<some-token>",
       "baseUrl": "http://127.0.0.1:8082"
     }
   }

---

WARN  Config auto-restored from last-known-good: /home/<user>/.openclaw/openclaw.json (reload-invalid-config)
WARN  {"subsystem":"gateway/reload"} config reload restored last-known-good config after invalid-config
RAW_BUFFERClick to expand / collapse

Summary

Adding a providers.<id> block (with apiKey + baseUrl) to ~/.openclaw/openclaw.json causes the gateway to revert to last-known-good on the next reload, with no operator-visible reason. The rejected config is preserved on disk (good), but no log line, doctor check, or CLI output reveals which field/value/schema rule the validator objected to.

Version

  • OpenClaw 2026.4.25 (npm)
  • Node 22.22.2
  • Linux (Debian, x86_64)

Repro

  1. Clean install: npm i -g openclaw, then openclaw doctor --repair --non-interactive --force --yes, then systemctl --user start openclaw-gateway. Verify gateway is healthy. Existing providers: only copilot-proxy and github-copilot.

  2. Edit ~/.openclaw/openclaw.json. Add a top-level providers.anthropic block:

    "providers": {
      "anthropic": {
        "apiKey": "<some-token>",
        "baseUrl": "http://127.0.0.1:8082"
      }
    }

    And change agents.main.models.primary to "anthropic/claude-3-5-haiku-latest" (which IS a valid catalog model — verified via openclaw infer model providers).

  3. openclaw gateway restart.

Expected

Either the config is accepted, or the validator logs which field, JSON path, or schema rule caused the rejection.

Actual

The patched file is moved aside to ~/.openclaw/openclaw.json.clobbered.<timestamp> and the previous good file is restored. The only relevant log lines:

WARN  Config auto-restored from last-known-good: /home/<user>/.openclaw/openclaw.json (reload-invalid-config)
WARN  {"subsystem":"gateway/reload"} config reload restored last-known-good config after invalid-config

No schema error, no JSON path, no field name. Nothing in openclaw doctor output. Nothing additional in journalctl.

diff between openclaw.json.last-good and openclaw.json.clobbered.<ts> is exactly the new providers block + the primary-model change. No other edits, no whitespace artifacts, no encoding issues.

Why this matters

Anyone trying to wire a custom-baseUrl provider — LiteLLM, a local OpenAI-compat proxy, OpenRouter, an internal mTLS endpoint, etc. — will hit this and have no diagnostic to work from. The error UX makes it look like the config save worked; the operator only finds out by running infer model run and seeing it silently fall back to a different provider/model (the silent-fallback behavior amplifies the impact, but is a separate observation worth its own report).

Workaround

None found. Adding the credential to ~/.openclaw/agents/main/agent/auth-profiles.json resolves the "no API key" error path, but that schema has no slot for baseUrl, so requests still go to the default endpoint (api.anthropic.com for the anthropic provider) and return 401 invalid x-api-key.

Suggested fix

Surface the validation failure reason in the gateway/reload subsystem log at minimum: JSON path of the offending field and the schema rule that failed. If user-edited config is forbidden from setting some fields because they must come from openclaw infer model auth login, log that explicitly so operators stop trying.

Notes

Filed as part of a structured release-test pass on 2026.4.25 done on a dedicated rig (anker-4). I'm new to filing OpenClaw issues; happy to attach the clobbered/last-good files or a redacted gateway log excerpt if that helps.

extent analysis

TL;DR

The issue can be addressed by modifying the OpenClaw configuration validation to provide detailed error messages, specifically logging the JSON path of the offending field and the schema rule that failed during the gateway/reload subsystem log.

Guidance

  • Review the OpenClaw configuration validation logic to identify why the providers.<id> block addition causes a silent config revert.
  • Consider adding logging statements to the validation code to capture and display the specific field or schema rule causing the validation failure.
  • Investigate the openclaw doctor command to see if it can be enhanced to detect and report configuration issues related to custom providers and base URLs.
  • Examine the agents/main/agent/auth-profiles.json schema to determine if it can be extended to accommodate custom baseUrl settings for providers like Anthropics.

Example

No specific code example can be provided without access to the OpenClaw source code, but the idea would be to add logging or error handling in the configuration validation part of the code, similar to:

// Pseudo-code example, actual implementation depends on OpenClaw's codebase
if (!validateConfig(newConfig)) {
  const errorDetails = getValidationErrors(newConfig);
  logger.error(`Config validation failed: ${errorDetails.jsonPath} - ${errorDetails.schemaRule}`);
  // Log or return the detailed error message
}

Notes

The provided information suggests that the issue is related to the validation of custom provider configurations in OpenClaw. Without direct access to the OpenClaw codebase or more detailed logs, it's challenging to provide a precise fix. The guidance offered aims to point towards areas that could potentially resolve the issue or improve the diagnostic output.

Recommendation

Apply a workaround by manually validating the configuration changes before applying them, or wait for an update to OpenClaw that includes improved validation error messaging. Given the information, there's no clear path to an immediate fix without modifying

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 Config validator silently reverts providers.<id> writes with no operator-visible reason (2026.4.25) [1 pull requests, 1 comments, 2 participants]