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
- Restore the host connection and retry Enter — resetConnected() drops stale snapshots and prewarms every key on reconnect
- Read the inner message (the wrapped entry.lastError) to get the concrete command.list error code and act on that instead of the wrapper
- 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)
- 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
- Prewarm with warm() when a session scope mounts so Enter rarely waits on a cold pull
- Call resetConnected() on reconnect so failed entries cannot serve stale rejections
- Diagnose the inner lastError message, not the wrapper text
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
- command.execute failed: ${result.error.code}: ${result.error
- command.list failed: ${result.error.code}: ${result.error.me
- permission switch failed: ${result.error.code}: ${result.err
- context-not-found
- transport failure for ${channel}/${endpoint}: HTTP ${respons
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/65c089c4b0dbb83f.
Report an issue: GitHub.