deepseek-ai/deepseek-harness · error

session.models failed: ${result.error.code}: ${result.error.

Error message

session.models failed: ${result.error.code}: ${result.error.message}

What it means

ModelDirectory.load() fetches the routable model catalog via session.models. On failure it records status:'error' plus the code/message in its store and then throws 'session.models failed: <code>: <message>'. If the directory was disposed or a newer generation superseded this load, the store is left untouched and only the raw code/message throws.

Source

Thrown at packages/client/ui-model-selection/src/client/directory.ts:74

  ) {}

  /**
   * Refresh the advisory directory (both entries call this on open).
   * Failure preserves the last good groups and current selection.
   * @returns the fresh directory value.
   */
  async load(): Promise<SessionModels> {
    this.assertAvailable()
    const generation = ++this.generation
    this.store.update((s) => { s.status = 'loading'; s.error = null })
    const { result } = await this.sessions.models({ sessionId: this.sessionId })
    if (this.disposed || generation !== this.generation) {
      if (!result.ok) throw new Error(`${result.error.code}: ${result.error.message}`)
      return result.value
    }
    if (!result.ok) {
      this.store.update((s) => { s.status = 'error'; s.error = `${result.error.code}: ${result.error.message}` })
      throw new Error(`session.models failed: ${result.error.code}: ${result.error.message}`)
    }
    const { current, routable, groups, failures } = result.value
    this.store.update((s) => {
      s.current = current
      s.routable = routable
      s.groups = groups
      s.failures = failures
      s.status = 'ready'
      s.error = null
    })
    return result.value
  }

  /**
   * Select the complete provider/model/reasoning selection (both entries submit through here). Success
   * updates the shared current; failure surfaces on the store and throws so
   * each entry's own retry surface engages.
   * @param selection - provider, provider-owned model id, and optional adapter-owned effort.

View on GitHub (pinned to b150a551b8)

Solutions

  1. Retry the load once the provider is reachable — the store keeps the error text for the retry UI
  2. Read store status/error to surface the host-side refusal code to the user
  3. Confirm the session binding is live before reloading
Defensive patterns

Strategy: retry

Validate before calling

const snap = directory.store.getSnapshot()
if (snap.status === 'error' || snap.groups.length === 0) await directory.load()

Try / catch

try {
  await directory.load()
} catch {
  renderModelErrorWithRetry(directory.store.getSnapshot().error) // status stays 'error' for the UI
}

Prevention

When it happens

Trigger: Opening or refreshing the model picker while the models RPC fails: provider catalog unreachable from the host, authorization failure, or the session dead. load() runs from resetConnected, apply, refresh, reload, and ModelSelect mount.

Common situations: Provider outage at host startup; expired provider credentials; opening the picker right after a reconnect before the session resynced.

Related errors


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