openclaw - 💡(How to fix) Fix Regression: `agents.*.heartbeat.model` schema rejects both object and array fallback forms on 2026.5.6, despite #17582 closing as COMPLETED on 2026-02-23 [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#81453Fetched 2026-05-14 03:32:06
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
2
Author
Timeline (top)
closed ×1commented ×1

Error Message

2. Object form rejected

docker exec <container> openclaw config set "agents.defaults.heartbeat.model"
'{"primary":"openrouter/google/gemini-2.5-flash","fallbacks":["mistralai/mistral-small"]}'
--strict-json --dry-run

Output:

Error: Dry run failed: config schema validation failed.

- - agents.defaults.heartbeat.model: Invalid input: expected string, received object

Root Cause

Heartbeat is the gateway's liveness signal in unattended deployments (cron-only contact for hours-to-days at a time). Without a fallback chain:

  1. Provider degradation (429s, deprecation, model removal) silences heartbeat with no automatic recovery.
  2. Operators must manually swap heartbeat models, which requires a config edit + container restart.
  3. Heartbeat alerts (the safety-net signal) can fail to fire BECAUSE of the very degradation they're meant to surface — circular failure.

Resolving this restores the symmetry between agents.*.model (fallback-supported) and agents.*.heartbeat.model (which has the same multi-provider availability concerns).

Fix Action

Fix / Workaround

DateIncident
2026-05-04 (S29)Mistral Small heartbeat model broke under 5.x lightContext shape change — heartbeat went silent until manual swap. Filed memory/2026-05-04-session-29-5.3-1-upgrade.md.
2026-05-07 (S31)Empty-heartbeat-file behaviour on 5.6 (separate non-bug).
2026-05-12 (S33-evening)Discovered heartbeat.model schema gap during a portfolio-intel fallback patch session — L14 lesson captured.

Local mitigation (we don't have one)

  • We cannot patch node_modules/openclaw/dist/* (operator policy: never edit node_modules).
  • Our heartbeat is configured with single-string primary (openrouter/google/gemini-2.5-flash).
  • Manual-swap procedure documented in our ops runbook.

Code Example

# 1. Schema dump shows string-only
docker exec <container> openclaw config schema 2>&1 | \
  jq '.properties.agents.properties.defaults.properties.heartbeat.properties.model'
# Output: { "type": "string" }

---

# 2. Object form rejected
docker exec <container> openclaw config set "agents.defaults.heartbeat.model" \
  '{"primary":"openrouter/google/gemini-2.5-flash","fallbacks":["mistralai/mistral-small"]}' \
  --strict-json --dry-run
# Output:
# Error: Dry run failed: config schema validation failed.
# - - agents.defaults.heartbeat.model: Invalid input: expected string, received object

---

# 3. Array form ALSO rejected
docker exec <container> openclaw config set "agents.defaults.heartbeat.model" \
  '["openrouter/google/gemini-2.5-flash","mistralai/mistral-small"]' \
  --strict-json --dry-run
# Output:
# Error: Dry run failed: config schema validation failed.
# - - agents.defaults.heartbeat.model: Invalid input: expected string, received array
RAW_BUFFERClick to expand / collapse

#17582 ("Feature Request: Support model fallback chain for heartbeat.model") was closed as COMPLETED on 2026-02-23. The proposal was to accept three shapes at heartbeat.model:

  • string (current/legacy): "openrouter/google/gemini-2.5-flash"
  • array (fallback chain): ["primary-model", "fallback-1"]
  • object (matching agent format): { "primary": "...", "fallbacks": [...] }

On 2026.5.6 (current stable; live schema dump verified S34 2026-05-13), the schema at agents.defaults.heartbeat.model is {"type": "string"} and rejects both array and object forms with explicit dry-run validation errors. The "completed" feature is not reachable through config in 5.6.

This is filed as a regression report, not a duplicate of #17582. Possibilities for upstream triage:

  • The fix shipped in some intermediate version and was reverted/regressed before 5.6
  • The fix was marked completed but not merged
  • The fix landed under a different field name and the original heartbeat.model schema was deliberately kept narrow
  • We're missing a version-specific config-shape unlock

Repro

On [email protected] (live verified via docker exec clawdbot openclaw config schema):

# 1. Schema dump shows string-only
docker exec <container> openclaw config schema 2>&1 | \
  jq '.properties.agents.properties.defaults.properties.heartbeat.properties.model'
# Output: { "type": "string" }
# 2. Object form rejected
docker exec <container> openclaw config set "agents.defaults.heartbeat.model" \
  '{"primary":"openrouter/google/gemini-2.5-flash","fallbacks":["mistralai/mistral-small"]}' \
  --strict-json --dry-run
# Output:
# Error: Dry run failed: config schema validation failed.
# - - agents.defaults.heartbeat.model: Invalid input: expected string, received object
# 3. Array form ALSO rejected
docker exec <container> openclaw config set "agents.defaults.heartbeat.model" \
  '["openrouter/google/gemini-2.5-flash","mistralai/mistral-small"]' \
  --strict-json --dry-run
# Output:
# Error: Dry run failed: config schema validation failed.
# - - agents.defaults.heartbeat.model: Invalid input: expected string, received array

Either failure on its own would be a documentation/feature gap; both together against a "completed" tracking issue indicates regression.

Where the COMPLETED claim came from

#17582 body:

Proposed Behavior

Allow heartbeat.model to accept either:

  • A string (current behavior): "nvidia/kimi-k2.5"
  • An array (fallback chain): ["nvidia/kimi-k2.5", "nvidia/minimaxai/minimax-m2.1"]
  • An object (matching agent format): { "primary": "...", "fallbacks": ["..."] }

This should apply to both agents.defaults.heartbeat.model and per-agent heartbeat.model.

State: closedAt: 2026-02-23T21:17:42Z / stateReason: COMPLETED. No explicit closing PR found via gh search prs "fixes #17582".

The related-but-distinct #19445 ("agents.defaults.heartbeat.model Config Ignored", closed COMPLETED 2026-02-25) referenced #17582 directly and included the same dict-form proposal in its body. Both closed within 48h of each other.

Production evidence

We hit the absence-of-fallbacks operationally during 2026.5.x:

DateIncident
2026-05-04 (S29)Mistral Small heartbeat model broke under 5.x lightContext shape change — heartbeat went silent until manual swap. Filed memory/2026-05-04-session-29-5.3-1-upgrade.md.
2026-05-07 (S31)Empty-heartbeat-file behaviour on 5.6 (separate non-bug).
2026-05-12 (S33-evening)Discovered heartbeat.model schema gap during a portfolio-intel fallback patch session — L14 lesson captured.

With fallback chain support, the 2026-05-04 incident would have failed over silently; instead it required manual config edit + restart.

Why this matters

Heartbeat is the gateway's liveness signal in unattended deployments (cron-only contact for hours-to-days at a time). Without a fallback chain:

  1. Provider degradation (429s, deprecation, model removal) silences heartbeat with no automatic recovery.
  2. Operators must manually swap heartbeat models, which requires a config edit + container restart.
  3. Heartbeat alerts (the safety-net signal) can fail to fire BECAUSE of the very degradation they're meant to surface — circular failure.

Resolving this restores the symmetry between agents.*.model (fallback-supported) and agents.*.heartbeat.model (which has the same multi-provider availability concerns).

Hypothesised resolutions for upstream triage

Resolution A — schema widening was reverted post-#17582 closure

Re-apply the schema widening at agents.defaults.heartbeat.model and agents.list[*].heartbeat.model to accept anyOf [string, array of strings, object{primary, fallbacks, timeoutMs}]. Wire the resolver to the existing resolveAgentModelFallbacksOverride codepath used by the agent-defaults resolver (agent-scope-B6RIBoEj.js:177 in the 5.6 bundle).

Resolution B — feature was deferred under different field name

If the original intent was preserved at a different config path (e.g. agents.*.heartbeat.fallbacks as a sibling array field), document it in the schema and link from #17582. We grep'd openclaw config schema for heartbeat paths and only found model: string + every, compaction.enabled, enabled — no fallbacks sibling.

Resolution C — feature was rolled into a different mechanism

If heartbeat is now expected to use a provider-aware retry layer (e.g. OpenRouter routing rules, in-process model-router), document that #17582's user-facing schema proposal is intentionally not implemented and link the alternative.

Suggested test cases

  1. Schema parity test: for any config path that accepts anyOf [string, object] at one layer, sibling heartbeat.model should accept the same shapes — or the test should explicitly assert string-only and document why.
  2. Fallback resolution test: configure heartbeat with a definitely-broken primary and a working fallback; assert heartbeat fires successfully via the fallback.
  3. Regression guard: import openclaw config schema output into a snapshot test so future narrowing of heartbeat.model is caught at PR time.

Local mitigation (we don't have one)

  • We cannot patch node_modules/openclaw/dist/* (operator policy: never edit node_modules).
  • Our heartbeat is configured with single-string primary (openrouter/google/gemini-2.5-flash).
  • Manual-swap procedure documented in our ops runbook.

If a runtime resolver supports a wider shape than the schema admits, please share the env var or config path that unlocks it. Otherwise we'll wait for the schema fix.

Cross-reference

  • #17582 (closed COMPLETED 2026-02-23) — Feature Request: Support model fallback chain for heartbeat.model — original proposal
  • #19445 (closed COMPLETED 2026-02-25) — agents.defaults.heartbeat.model Config Ignored — included same proposal in body
  • #74217 (open) — Heartbeat model leaks into user session status/runtime model — related-but-distinct (privacy/state leak, not fallback config)
  • 2026.5.4 release notes — added event-loop starvation signals to channels status (#76327, separate issue we're also filing as P5); no heartbeat schema changes mentioned

Why not a comment on #17582

#17582 is in COMPLETED state; commenting on a closed issue is lower-visibility for active triage. A new issue with the explicit regression-report framing surfaces the gap better. Linking back to #17582 in the body provides full history.

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 - 💡(How to fix) Fix Regression: `agents.*.heartbeat.model` schema rejects both object and array fallback forms on 2026.5.6, despite #17582 closing as COMPLETED on 2026-02-23 [1 comments, 2 participants]