vercel/ai · error

`Harness session ${this.sessionId} has no unfinished turn to

Error message

`Harness session ${this.sessionId} has no unfinished turn to continue.`

What it means

Also thrown by `requireContinuableTurn()` from `continueTurn()`, for the 'idle' state: no turn exists to continue. Continuation requires a prior turn that paused or suspended; with turnState 'idle' (no turn started yet, or the previous turn already finished or failed) there is nothing to resume and the library refuses. Start a turn with `promptTurn()` first.

Source

Thrown at packages/harness/src/agent/harness-agent-session.ts:664

    throw new Error(
      `Harness session ${this.sessionId} has an unfinished turn and must be continued before accepting a new prompt.`,
    );
  }

  private requireContinuableTurn(): void {
    if (
      this.turnState === 'awaiting-approval' ||
      this.turnState === 'awaiting-tool-result' ||
      this.turnState === 'suspended'
    ) {
      return;
    }
    if (this.turnState === 'running') {
      throw new Error(
        `Harness session ${this.sessionId} already has a turn in progress.`,
      );
    }
    throw new Error(
      `Harness session ${this.sessionId} has no unfinished turn to continue.`,
    );
  }

  private markAwaitingApprovalIfActive(): void {
    if (this.sessionState === 'active') {
      this.clearActivePromptControl();
      this.turnState = 'awaiting-approval';
    }
  }

  private markAwaitingToolResultIfActive(): void {
    if (this.sessionState === 'active') {
      this.clearActivePromptControl();
      this.turnState = 'awaiting-tool-result';
    }
  }

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Call `promptTurn()` to start a turn before any continueTurn; only continue turns that are awaiting approval/tool-result or suspended.
  2. Check `hasUnfinishedTurn()` before continueTurn and fall back to promptTurn (or exit the loop) when it is false.
  3. After a turn failure, start a new turn with promptTurn rather than continueTurn.
  4. Fix loop logic so continueTurn is called at most once per suspension, and stop iterating when the turn completes.

Example fix

// before
// previous turn already finished
session.continueTurn({ ... }); // throws: no unfinished turn

// after
if (session.hasUnfinishedTurn()) {
  const cont = session.continueTurn({ ... });
  await cont.ready;
} else {
  const turn = session.promptTurn({ prompt: 'new task', ... });
  await turn.ready;
}
Defensive patterns

Strategy: validation

Validate before calling

if (!session.hasUnfinishedTurn()) {
  throw new NothingToContinueError(); // start with promptTurn instead
}

Try / catch

try {
  session.continueTurn({ ... });
} catch (error) {
  if (error instanceof Error && /has no unfinished turn to continue/.test(error.message)) {
    session.promptTurn({ prompt, ... }); // nothing to continue; start fresh
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: Calling `continueTurn()` on a freshly created/resumed session before any promptTurn; calling continueTurn after the previous turn already completed or failed (state reset to idle by finishTrackedTurn); calling continueTurn twice after a suspension — the first continue starts a running turn, and once it finishes, a second continue finds idle.

Common situations: Orchestration loops that unconditionally continueTurn each iteration without checking whether the prior turn finished; retrying a failed turn with continueTurn instead of promptTurn; resuming a session from persisted state where the stored continuation was already consumed; off-by-one in slice-based schedulers that continue after the final slice.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/1a661006e611e325. Report an issue: GitHub.