deepseek-ai/deepseek-harness · error

command directory warmup failed: ${entry.lastError instanceo

Error message

command directory warmup failed: ${entry.lastError instanceof Error ? entry.lastError.message : String(entry.lastError)}

What it means

The session-keyed CommandDirectory caches each session's slash-command catalog. ensureReady() strong-waits until a servable snapshot exists (Enter adjudication requires the directory to be reached): cold/failed entries launch refresh(), pending entries join the in-flight pull. When the winning pull rejects, its stored entry.lastError is rethrown wrapped as 'command directory warmup failed: ...' — the inner text is almost always the underlying command.list RPC error.

Source

Thrown at packages/client/ui-commands/src/client/directory.ts:130

  }

  /**
   * Strong-wait until one session's catalog is servable (the enter-
   * adjudication "directory must be reached" rule): ready returns at once;
   * cold/failed launch a fresh pull; pending joins the flying one. Rejects
   * when the awaited pull fails or the signal aborts.
   * @param sessionId - session key.
   * @param signal - attempt-scoped abort (the SubmitAttempt signal).
   * @returns the hot command snapshot.
   */
  async ensureReady(sessionId: SessionId, signal: AbortSignal): Promise<readonly CommandDescriptor[]> {
    const entry = this.entry(sessionId)
    while (true) {
      if (entry.state === 'ready') return entry.commands
      if (entry.state !== 'pending') void this.refresh(sessionId)
      await settled(entry, signal)
      if (entry.state === 'failed') {
        throw new Error(`command directory warmup failed: ${entry.lastError instanceof Error ? entry.lastError.message : String(entry.lastError)}`)
      }
      // Still pending (the awaited pull was superseded) → wait for the winner.
    }
  }

  private entry(sessionId: SessionId): Entry {
    let entry = this.entries.get(sessionId)
    if (entry === undefined) {
      entry = new Entry()
      this.entries.set(sessionId, entry)
    }
    return entry
  }
}

/** One settlement tick for one entry: resolves at the next winning publish, rejects on abort. */
function settled(entry: Entry, signal: AbortSignal): Promise<void> {
  if (signal.aborted) return Promise.reject(abortReason(signal))

View on GitHub (pinned to b150a551b8)

Solutions

  1. Restore the host connection and retry Enter — resetConnected() drops stale snapshots and prewarms every key on reconnect
  2. Read the inner message (the wrapped entry.lastError) to get the concrete command.list error code and act on that instead of the wrapper
  3. Confirm the session is alive and the host serves command.list for this sessionId (subagent-addressed sessions short-circuit to an empty list without any RPC)
  4. In UI code, catch this error and offer a retry affordance instead of surfacing a raw rejection
Defensive patterns

Strategy: retry

Validate before calling

if (directory.status(sessionId) !== 'ready') {
  await directory.refresh(sessionId) // start a fresh epoch before strong-waiting
}
const commands = await directory.ensureReady(sessionId, signal)

Try / catch

try {
  return await directory.ensureReady(sessionId, signal)
} catch (error) {
  if (signal.aborted) throw error
  await directory.refresh(sessionId) // a new epoch clears the failed state
  return directory.ensureReady(sessionId, signal)
}

Prevention

When it happens

Trigger: Pressing Enter on a slash-command line (matchEnter) or calling list() while the session's cache entry is in state 'failed': the latest refresh() pull (the epoch winner) rejected because the command.list RPC returned an error, the transport dropped, or the attempt's AbortSignal fired while waiting on settled(entry, signal).

Common situations: Web client loses the host connection (server restart, network drop, standby/resume) and the user hits Enter on a slash command before a successful reconnect; the host rejects command.list for a session it already closed; first paint where the scope-birth warm hook races a dying connection.

Related errors


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