deepseek-ai/deepseek-harness · error

command.list failed: ${result.error.code}: ${result.error.me

Error message

command.list failed: ${result.error.code}: ${result.error.message}

What it means

The ui-commands service wires CommandDirectory's pull callback to ctx.remote.commands.list(sessionId). When that RPC resolves non-ok, the pull throws 'command.list failed: <code>: <message>'; refresh() stores it as entry.lastError, and it later resurfaces wrapped from ensureReady() (error 180) or propagates directly to anyone awaiting the refresh path. Subagent-addressed sessions skip the RPC and return an empty list.

Source

Thrown at packages/client/ui-commands/src/client/service.ts:141

  private readonly directory: CommandDirectory
  private readonly live: LiveState = { contributions: new Map(), decorations: new Map(), popups: new Map() }
  /** `command`-namespace translator (composer refusal notices). */
  private readonly t: TranslateNS<'command'>

  /**
   * @param ctx - owning root context (plugin fiber; the service registers
   * itself as `command` and follows that fiber's lifetime).
   */
  constructor(ctx: Context) {
    super(ctx, 'commandUi')
    const locale = ctx.get('locale')
    if (locale === undefined) throw new Error('ui-commands: locale service unavailable')
    this.t = locale.bind('command')
    this.directory = new CommandDirectory(async (sessionId) => {
      if (this.sessions().subagentAddress(sessionId) !== undefined) return []
      const result = await ctx.remote.commands.list(sessionId)
      if (!result.ok) throw new Error(`command.list failed: ${result.error.code}: ${result.error.message}`)
      return result.value
    })
    const inputTriggers = ctx.get('inputTriggers')
    if (inputTriggers === undefined) throw new Error('ui-commands: slash service unavailable')
    ctx.effect(() => inputTriggers.registerSource({
      trigger: '/',
      name: 'command',
      candidates: (session, req) => this.candidates(session, req),
      onPick: pick => this.dispatch(pick),
      matchSpace: (session, token) => this.matchSpace(session, token),
      matchEnter: (session, line, signal, envelope) => this.matchEnter(session, line, signal, envelope),
      warm: (session) => { this.directory.warm(session.sessionId) },
    }), 'command: slash source')
    ctx.remote.$on('commands/change', () => { this.directory.invalidateAll() })
    // A preset switch changes which commands one session's agent resolves and
    // registers nothing globally, so the registry-wide signal above never
    // fires for it: repull that key alone, soft, so the old snapshot serves
    // the menu until the new one lands.

View on GitHub (pinned to b150a551b8)

Solutions

  1. Read the embedded result.error.code in the thrown message to identify the host-side refusal reason
  2. Verify client and host run matching protocol versions so commands.list exists with the same request fields
  3. Confirm the session is live and not subagent-addressed before pulling
  4. Reconnect and let resetConnected() repull once the transport is restored
Defensive patterns

Strategy: try-catch

Validate before calling

if (sessions.subagentAddress(sessionId) !== undefined) return [] // no RPC needed
if (!connectionHealthy()) await reconnect()

Try / catch

try {
  return await remote.commands.list(sessionId)
} catch (error) {
  reportDegradedCatalog(sessionId, error) // empty catalog plus notice, never a silent success
  throw error
}

Prevention

When it happens

Trigger: Any catalog pull — warm(sessionId), an explicit refresh(sessionId), the background repull after invalidateAll() (a commands-changed event), or resetConnected() on reconnect — where commands.list responds with a non-ok result: unknown session, permission denial, or a host-side handler failure.

Common situations: Client and host version skew (host predates the commands.list RPC or changed its request fields); session terminated server-side while the UI still shows it; reverse proxy or gateway returning an error envelope; the host plugin serving commands failed to activate.

Related errors


AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24). Data as JSON: /api/errors/9e0d95a27c9ab898. Report an issue: GitHub.