bug(cli): duplicate React keys in CommandAutocomplete — "clear" and "help" collisions #193

Closed
opened 2026-03-17 02:11:40 +00:00 by jason.woltje · 0 comments
Owner

Description

The CommandAutocomplete component renders duplicate React keys, triggering warnings:

Warning: Encountered two children with the same key, `clear`.
Warning: Encountered two children with the same key, `help`.

This happens because the autocomplete renders commands from both the local registry (CommandRegistry.LOCAL_COMMANDS) and the gateway manifest (commands:manifest). Both sources include clear, help, status, and new — the local commands and the gateway-registered commands have the same names, creating key collisions when rendered together.

Location

  • packages/cli/src/tui/components/command-autocomplete.tsx line 12 — uses cmd.name as React key
  • packages/cli/src/tui/commands/registry.tsgetAll() merges local + gateway commands without deduplication

Root Cause

CommandRegistry.getAll() concatenates LOCAL_COMMANDS and gatewayManifest.commands without deduplicating. Several commands exist in both:

  • clear — local (display clear) + gateway (context clear)
  • help — local + gateway
  • status — local + gateway
  • new — local + gateway

The CommandAutocomplete component then maps over this merged list using cmd.name as the React key, causing collisions.

Fix Options

  1. Deduplicate in getAll() — gateway commands take precedence over local commands with the same name. Local-only commands remain.
  2. Use unique key in component — e.g., key={\${cmd.scope}-${cmd.name}`}` to differentiate by source.
  3. Both — deduplicate for correctness AND use scoped keys for safety.

Option 3 is recommended.

Stack Trace

at CommandAutocomplete (packages/cli/src/tui/components/command-autocomplete.tsx:12:3)
at InputBar (packages/cli/src/tui/components/input-bar.tsx:28:10)
at TuiApp (packages/cli/src/tui/app.tsx:30:3)
## Description The `CommandAutocomplete` component renders duplicate React keys, triggering warnings: ``` Warning: Encountered two children with the same key, `clear`. Warning: Encountered two children with the same key, `help`. ``` This happens because the autocomplete renders commands from both the local registry (`CommandRegistry.LOCAL_COMMANDS`) and the gateway manifest (`commands:manifest`). Both sources include `clear`, `help`, `status`, and `new` — the local commands and the gateway-registered commands have the same names, creating key collisions when rendered together. ## Location - `packages/cli/src/tui/components/command-autocomplete.tsx` line 12 — uses `cmd.name` as React key - `packages/cli/src/tui/commands/registry.ts` — `getAll()` merges local + gateway commands without deduplication ## Root Cause `CommandRegistry.getAll()` concatenates `LOCAL_COMMANDS` and `gatewayManifest.commands` without deduplicating. Several commands exist in both: - `clear` — local (display clear) + gateway (context clear) - `help` — local + gateway - `status` — local + gateway - `new` — local + gateway The `CommandAutocomplete` component then maps over this merged list using `cmd.name` as the React key, causing collisions. ## Fix Options 1. **Deduplicate in `getAll()`** — gateway commands take precedence over local commands with the same name. Local-only commands remain. 2. **Use unique key in component** — e.g., `key={\`\${cmd.scope}-\${cmd.name}\`}` to differentiate by source. 3. **Both** — deduplicate for correctness AND use scoped keys for safety. Option 3 is recommended. ## Stack Trace ``` at CommandAutocomplete (packages/cli/src/tui/components/command-autocomplete.tsx:12:3) at InputBar (packages/cli/src/tui/components/input-bar.tsx:28:10) at TuiApp (packages/cli/src/tui/app.tsx:30:3) ```
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#193