deepseek-ai/deepseek-harness · error

conversation.cancel failed: ${result.error.code}: ${result.e

Error message

conversation.cancel failed: ${result.error.code}: ${result.error.message}

What it means

cancel() aborts the scoped session's in-flight turn via session.cancel while preserving the Queue. A non-ok result throws 'conversation.cancel failed: <code>: <message>' — most commonly because no turn is in flight anymore, so there is nothing to cancel.

Source

Thrown at packages/client/ui-conversation/src/client/service.ts:302

  /** Apply one operation to a pending queue occurrence. */
  async updateQueue(itemId: QueueItemId, action: QueueAction): Promise<void> {
    const session = this.scopedSession('updateQueue')
    const result = await session.updateQueue(itemId, action)
    if (!result.ok) {
      if (
        action.kind === 'steer'
        && (result.error.code === 'steer-unavailable' || result.error.code === 'queue-item-not-found')
      ) return
      throw new Error(`conversation.updateQueue failed: ${result.error.code}: ${result.error.message}`)
    }
  }

  /** Cancel the scoped session's in-flight turn while preserving Queue (failures land in promptError and reject, as in send). */
  async cancel(): Promise<void> {
    const session = this.scopedSession('cancel')
    const result = await session.cancel()
    if (!result.ok) throw new Error(`conversation.cancel failed: ${result.error.code}: ${result.error.message}`)
  }

  /** Pull one older history page for the scoped Session. */
  async loadOlder(): Promise<void> {
    await this.scopedSession('loadOlder').loadOlder()
  }

  /** Resolve the caller scope's session face or throw on root contexts. */
  private scopedSession(op: string): SessionFace {
    const id = this.scopeId(op)
    const binding = this.requireSessions().binding(id)
    if (binding === undefined) throw new Error(`conversation.${op}: session "${id}" resolved no binding`)
    return binding.session
  }

  /** Read the caller's session scope tag via the sessions service; root contexts fail loud. */
  private scopeId(op: string): SessionId {
    const id = this.requireSessions().scopeOf(this.ctx)

View on GitHub (pinned to b150a551b8)

Solutions

  1. Treat no-active-turn codes as success — the goal (no running turn) already holds
  2. Drive the Stop button's enabled state from the live frame so it is disabled when no turn is in flight
  3. For transport codes, reconnect and re-check session state before retrying
Defensive patterns

Strategy: try-catch

Validate before calling

if (!turnInFlight(sessionSnapshot)) return // nothing to cancel

Try / catch

try {
  await conversation.cancel()
} catch (error) {
  if (isNoActiveTurn(error)) return // the goal already holds
  throw error
}

Prevention

When it happens

Trigger: Clicking cancel after the turn already finished (host answers a no-active-turn style code); cancelling a session that was closed; transport failure during the cancel call.

Common situations: A Stop button racing natural turn completion; double-click on Stop; cancelling exactly as the connection drops.

Related errors


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