openclaw - 💡(How to fix) Fix Direct mutation of Commander's internal commands array bypasses internal bookkeeping [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#83896Fetched 2026-05-20 03:47:18
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
1
Timeline (top)
labeled ×5commented ×1unsubscribed ×1

Fix Action

Fix / Workaround

Severity: medium / Confidence: medium / Category: maintainability Triage: risk 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


Standardized clawpatch finding. Persistent in v2026.5.18 (not resolved by upgrading from v2026.5.12). Finding ID: fnd_sig-feat-cli-command-0f69ccd6ad-_780a07cf0d.

Code Example

const commands = program.commands as Command[];
  const index = commands.indexOf(command);
  if (index < 0) {
    return false;
  }
  commands.splice(index, 1);
RAW_BUFFERClick to expand / collapse

Severity: medium / Confidence: medium / Category: maintainability Triage: risk 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

Evidence

  • src/cli/program/command-tree.ts:4-9 (removeCommand)
const commands = program.commands as Command[];
  const index = commands.indexOf(command);
  if (index < 0) {
    return false;
  }
  commands.splice(index, 1);

Reasoning

program.commands is typed as readonly Command[] in Commander's public API. Casting it to Command[] and splicing it mutates the array in place. Commander internally tracks commands in a _name lookup map and maintains parent references on each sub-command object; splicing the array does not clear those. If Commander ever iterates its name map (e.g. during parseAsync or help generation) after a splice, the removed command's entry may still be found via the name map even though it is absent from the array, producing inconsistent results. This is also a fragile dependency on an undocumented internal representation that can break silently across Commander minor versions.

Reproduction

Register a command, call removeCommandByName, then call program.parseAsync(['node','cli','<removed-command>']); depending on Commander version, it may still route to the removed command.

Recommendation

Use Commander's public removeCommand API if available in the pinned version, or track placeholder commands in the registry layer rather than surgically removing them from the live program tree.

Why existing tests miss this

No tests for command-tree.ts are present in the provided test suite; the associated test file targets a different module.

Suggested regression test

Register a command, call removeCommandByName, and assert both program.commands.find(c => c.name() === name) and program.parseAsync with that name correctly reflect removal.

Minimum fix scope

src/cli/program/command-tree.ts removeCommand function


Standardized clawpatch finding. Persistent in v2026.5.18 (not resolved by upgrading from v2026.5.12). Finding ID: fnd_sig-feat-cli-command-0f69ccd6ad-_780a07cf0d.

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 Direct mutation of Commander's internal commands array bypasses internal bookkeeping [1 comments, 2 participants]