Fix PreparedModelCatalogConfigReplacedError on replies with OpenClaw >= 2026.9.x - #307
Open
cuijianzhuang wants to merge 8 commits into
Open
cuijianzhuang wants to merge 8 commits into
cuijianzhuang wants to merge 8 commits into
Conversation
The monitor loop captured the `ctx.cfg` snapshot handed to `gateway.startAccount` and reused it for every reply. OpenClaw >= 2026.9.x republishes the config object on each config write or reload and rejects calls whose config no longer matches the published prepared-model-catalog owner, so inbound messages were received while every reply failed with `PreparedModelCatalogConfigReplacedError`. The account is only restarted for `channels.openclaw-weixin.*` changes, so edits elsewhere left us holding a superseded object indefinitely. Each inbound message now re-reads the host's current runtime config, using the same accessors the bundled channels use: `createRuntimeConfigReader` first, then `selectApplicableRuntimeConfig`, then `getRuntimeConfigSnapshot`/`getRuntimeConfig`. They are looked up through a dynamic import so hosts down to the declared peer minimum (2026.5.12), which publish neither module nor export, keep loading and simply fall back to the startup snapshot. `scripts/hotfix-live-config.mjs` applies the equivalent patch to an already installed build (backup written, `--revert` restores it) for users who cannot wait for a release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NAnMV1vUceCgm9TnVRmmtW
Replace the runtime probe with a static, typed dependency on the host's own resolution rule. `selectApplicableRuntimeConfig` — what `createRuntimeConfigReader` is built on, and what the bundled channels resolve through — exists in `openclaw/plugin-sdk/runtime-config-snapshot` from the declared host minimum (2026.5.12) onwards, verified against the published 2026.5.12, 2026.8.1 and 2026.9.4 type surfaces, so nothing needs probing and no host requirement changes. `createLiveConfigResolver` is now synchronous and evaluates the rule per call rather than caching the decision, which keeps it correct across gateway reloads. `MonitorWeixinOpts.config` is replaced by the required `getConfig` resolver so no caller can pass a snapshot that goes stale. The hotfix script for already installed builds applies the same rule, and now reports "no patch needed" on builds that already carry the fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NAnMV1vUceCgm9TnVRmmtW
The shipped fix in src/config/live-config.ts is the supported path; keep only that. Removes scripts/hotfix-live-config.mjs and its changelog mentions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NAnMV1vUceCgm9TnVRmmtW
Fix PreparedModelCatalogConfigReplacedError on replies with OpenClaw >= 2026.9.x
createLiveConfigResolver re-evaluated selectApplicableRuntimeConfig on every call against the startup ctx.cfg. The host matches that object against its current source snapshot, so after the first config write that changes content the match fails and the resolver falls back to the stale startup config - PreparedModelCatalogConfigReplacedError returns on every reply. Mirror the host's createRuntimeConfigReader instead: decide once whether the startup config is the host's, then always follow the current runtime snapshot (keeping scoped configs). Use the host reader when exported; hosts back to 2026.5.12 get an equivalent built on selectApplicableRuntimeConfig. Tests now model real config writes (new source object) and cover both host variants; the previous tests passed only because the mock never replaced the source snapshot. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…-decision fix: latch the live-config follow decision at account start
npm run ci failed at format:check on the destructuring added in the previous commit. No behaviour change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
style: format live-config.ts with oxfmt
Contributor
|
Thanks for working on the live-config side of this. We tested the current head ( The remaining gap is that Weixin calls the legacy low-level |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes an issue where replies fail with
PreparedModelCatalogConfigReplacedErroron OpenClaw hosts >= 2026.9.x by resolving the host's current runtime config for each inbound message instead of reusing a stale startup snapshot.Problem
The monitor loop was pinning the
ctx.cfgsnapshot handed togateway.startAccountand reusing it for every reply. Newer hosts (>= 2026.9.x) republish the config object on each config write or reload and reject calls whose config no longer matches the published prepared-model-catalog owner. This caused:PreparedModelCatalogConfigReplacedErrorchannels.openclaw-weixin.*changes)Solution
New module
src/config/live-config.ts: IntroducescreateLiveConfigResolver()which wraps the host'sselectApplicableRuntimeConfigrule to resolve the current runtime config per message. This rule:Updated
MonitorWeixinOpts: Changedconfigparameter togetConfig: LiveConfigResolverto resolve config per message instead of at startupUpdated
monitorWeixinProvider: CallsgetConfig()when processing each message instead of using a captured snapshotUpdated
weixinPlugin: Creates aLiveConfigResolverfrom the startup config and passes it to the monitorImplementation Details
selectApplicableRuntimeConfigfromopenclaw/plugin-sdk/runtime-config-snapshot(available since declared minimum version 2026.5.12)src/config/live-config.test.tscovering startup config, republished configs, scoped configs, and gateway reloads