openclaw - 💡(How to fix) Fix Rejected promise cached permanently in getConfigSnapshot

Official PRs (…)
ON THIS PAGE

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…

Error Message

The ??= operator stores the promise returned by readConfigFileSnapshot() before it settles. If that promise rejects (e.g. due to a transient filesystem error), the rejected promise is permanently stored in the module-level configSnapshotPromise variable. Every subsequent call to getConfigSnapshot() returns the same rejected promise for the lifetime of the process, causing all CLI commands that rely on config validation to fail with the original transient error rather than retrying. The VITEST guard on line 30 bypasses this path for tests, which is why no existing test exercises the failure case. Simulate a temporary ENOENT on the config file path during the first call to ensureConfigReady, then call a second unrelated command in the same process: the second call will also reject with the same stale error.

Fix Action

Fix / Workaround

Severity: high / Confidence: high / Category: bug Triage: confirmed-bug Detected against: openclaw v2026.5.18 (latest stable at time of scan, 2026-05-18) Tooling: clawpatch 0.3.0 + acpx/claude-sonnet-4-5 via Brad Mills protocol (https://x.com/bradmillscan/status/2056377217437909178)


Standardized clawpatch finding submission. Persistent across v2026.5.12 → v2026.5.18 — not resolved by upgrading. Finding ID: fnd_sig-feat-cli-command-0f69ccd6ad-_c445579396.

Code Example

configSnapshotPromise ??= readConfigFileSnapshot();
  return configSnapshotPromise;
RAW_BUFFERClick to expand / collapse

Severity: high / Confidence: high / Category: bug Triage: confirmed-bug Detected against: openclaw v2026.5.18 (latest stable at time of scan, 2026-05-18) Tooling: clawpatch 0.3.0 + acpx/claude-sonnet-4-5 via Brad Mills protocol (https://x.com/bradmillscan/status/2056377217437909178)

Evidence

  • src/cli/program/config-guard.ts:33-34 (getConfigSnapshot)
configSnapshotPromise ??= readConfigFileSnapshot();
  return configSnapshotPromise;

Reasoning

The ??= operator stores the promise returned by readConfigFileSnapshot() before it settles. If that promise rejects (e.g. due to a transient filesystem error), the rejected promise is permanently stored in the module-level configSnapshotPromise variable. Every subsequent call to getConfigSnapshot() returns the same rejected promise for the lifetime of the process, causing all CLI commands that rely on config validation to fail with the original transient error rather than retrying. The VITEST guard on line 30 bypasses this path for tests, which is why no existing test exercises the failure case.

Reproduction

Simulate a temporary ENOENT on the config file path during the first call to ensureConfigReady, then call a second unrelated command in the same process: the second call will also reject with the same stale error.

Recommendation

Reject the cached promise and clear configSnapshotPromise on failure so the next call retries: configSnapshotPromise = readConfigFileSnapshot(); configSnapshotPromise.catch(() => { configSnapshotPromise = null; });

Why existing tests miss this

The VITEST branch on line 30 always bypasses the cache, so the rejection-caching path is never exercised in the test suite.

Suggested regression test

In a unit test that spies on readConfigFileSnapshot, make the first call reject, call ensureConfigReady twice, and assert the second call also invokes readConfigFileSnapshot again rather than re-throwing the same cached rejection.

Minimum fix scope

Single function getConfigSnapshot in src/cli/program/config-guard.ts


Standardized clawpatch finding submission. Persistent across v2026.5.12 → v2026.5.18 — not resolved by upgrading. Finding ID: fnd_sig-feat-cli-command-0f69ccd6ad-_c445579396.

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 Rejected promise cached permanently in getConfigSnapshot