openclaw - 💡(How to fix) Fix [Bug]: claude-cli harness selection has no fallback path when registration races with session resume (2026.5.x)

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…

selectAgentHarnessDecision() in selection-*.js (dist) throws MissingAgentHarnessError immediately when runtime === "claude-cli" and the registry snapshot doesn't contain it. Only codex runtime has a graceful fallback path (to pi harness) for the implicit-runtimeSource case — claude-cli, google-gemini-cli, and codex-cli runtimes all throw hard.

Root Cause

Root cause (dist trace)

selection-*.jsselectAgentHarnessDecision:

Fix Action

Fix / Workaround

Local workaround

Patching dist/selection-*.js with the above logic. Wiped on npm upgrade -g openclaw, so a proper upstream fix is needed.

Env

  • openclaw 2026.5.19
  • macOS Darwin 25.5.0 (arm64)
  • claude-cli backend via Anthropic plugin
  • activation.onStartup patched to true locally — race still fires on idle-resume.

Code Example

const pluginHarnesses = listPluginAgentHarnesses();        // snapshot taken once
const forced = pluginHarnesses.find(e => e.id === runtime);
if (forced) return ...;
if (runtime === "codex" && policy.runtimeSource === "implicit") return pi_fallback;  // ONLY codex has fallback
throw new MissingAgentHarnessError(runtime);               // claude-cli falls here

---

if (CLI_RUNTIME_ALIASES.has(runtime)) {
  return buildSelectionDecision({
    harness: piHarness,
    policy: { ...policy, runtime: "pi" },
    selectedReason: "cli_harness_pending_pi_fallback",
    candidates: listHarnessCandidates(pluginHarnesses),
  });
}
throw new MissingAgentHarnessError(runtime);

---

const reLookup = getRegisteredAgentHarness(runtime);
if (reLookup) return buildSelectionDecision({
  harness: reLookup,
  policy,
  selectedReason: "forced_plugin_relookup",
  candidates: listHarnessCandidates([reLookup]),
});
RAW_BUFFERClick to expand / collapse

Summary

selectAgentHarnessDecision() in selection-*.js (dist) throws MissingAgentHarnessError immediately when runtime === "claude-cli" and the registry snapshot doesn't contain it. Only codex runtime has a graceful fallback path (to pi harness) for the implicit-runtimeSource case — claude-cli, google-gemini-cli, and codex-cli runtimes all throw hard.

Symptom

After a session idle close, on resume the gateway surfaces:

⚠️ Requested agent harness "claude-cli" is not registered.

Shows up in Telegram channel replies and TUI banner. Sporadic, more frequent on slower plugin activation.

Root cause (dist trace)

selection-*.jsselectAgentHarnessDecision:

const pluginHarnesses = listPluginAgentHarnesses();        // snapshot taken once
const forced = pluginHarnesses.find(e => e.id === runtime);
if (forced) return ...;
if (runtime === "codex" && policy.runtimeSource === "implicit") return pi_fallback;  // ONLY codex has fallback
throw new MissingAgentHarnessError(runtime);               // claude-cli falls here

The Anthropic plugin's harness is registered at activation time, not load time. With activation.onStartup: false (default) the plugin activates lazily — losing the race with the first resume request when the live CLI session was closed by idle and gets respun.

Reproduction

  1. Configure claude-cli runtime (anthropic provider, claude-* model).
  2. Let a session idle until claude live session close: reason=idle fires.
  3. Send a new message → race window opens during plugin activation.
  4. Intermittent: the harness registry snapshot is empty → throw.

Suggested fix

Mirror the codexpi fallback in selectAgentHarnessDecision for all CLI runtime aliases (CLI_RUNTIME_ALIASES from model-runtime-aliases.ts):

if (CLI_RUNTIME_ALIASES.has(runtime)) {
  return buildSelectionDecision({
    harness: piHarness,
    policy: { ...policy, runtime: "pi" },
    selectedReason: "cli_harness_pending_pi_fallback",
    candidates: listHarnessCandidates(pluginHarnesses),
  });
}
throw new MissingAgentHarnessError(runtime);

Optionally do a second getRegisteredAgentHarness(runtime) lookup right before the fallback to catch the narrow race where registration finished between the snapshot call and the throw site:

const reLookup = getRegisteredAgentHarness(runtime);
if (reLookup) return buildSelectionDecision({
  harness: reLookup,
  policy,
  selectedReason: "forced_plugin_relookup",
  candidates: listHarnessCandidates([reLookup]),
});

Local workaround

Patching dist/selection-*.js with the above logic. Wiped on npm upgrade -g openclaw, so a proper upstream fix is needed.

Related

  • #81649 (Agent harness "anthropic" not registered, 2026.5.7) — closed as not planned; PR #81745 only added config validation, not runtime fallback.
  • #72434 (Regression in 2026.4.24: claude-cli not registered, all gateway requests fail).
  • #66260 (Gateway startup can skip Codex agent harness activation).

Env

  • openclaw 2026.5.19
  • macOS Darwin 25.5.0 (arm64)
  • claude-cli backend via Anthropic plugin
  • activation.onStartup patched to true locally — race still fires on idle-resume.

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