vercel/ai · error

`Harness session ${this.sessionId} already has a turn in pro

Error message

`Harness session ${this.sessionId} already has a turn in progress.`

What it means

Thrown by the private `requirePromptableTurn()` guard (invoked from `promptTurn()`) when the session's turn state is 'running', i.e. a prompt or continue turn is already executing. A session drives one turn at a time; starting a new prompt mid-turn would interleave model streams and tool state, so the library rejects it. Await the current turn's result (or abort/suspend it) before prompting again.

Source

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

  }

  private toResumeStateWithContinuation(options: {
    continueFrom: HarnessAgentContinueTurnState;
  }): HarnessAgentResumeSessionState {
    const { continueFrom } = options;
    return {
      type: 'resume-session',
      harnessId: continueFrom.harnessId,
      specificationVersion: continueFrom.specificationVersion,
      data: continueFrom.data,
      continueFrom,
    };
  }

  private requirePromptableTurn(): void {
    if (this.turnState === 'idle') 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 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(

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Await the in-flight turn's result (including its `ready` promise) before calling `promptTurn()` again.
  2. Serialize prompts: queue incoming prompts and process them one at a time per session, or create a separate session per concurrent task.
  3. Abort or suspend the running turn first (via the turn's prompt control / abortSignal, or `suspendTurn()`) before issuing a new prompt.
  4. Check `session.hasUnfinishedTurn()` and skip/queue the new prompt when it returns true.

Example fix

// before
session.promptTurn({ prompt, ... }); // not awaited
session.promptTurn({ prompt2, ... }); // throws: turn already in progress

// after
const turn = session.promptTurn({ prompt, ... });
await turn.ready;            // wait for the turn to settle
await turn.result;           // then start the next prompt
session.promptTurn({ prompt2, ... });
Defensive patterns

Strategy: validation

Validate before calling

if (session.hasUnfinishedTurn()) {
  throw new TurnBusyError(); // queue or await the in-flight turn first
}

Try / catch

try {
  session.promptTurn({ prompt, ... });
} catch (error) {
  if (error instanceof Error && /already has a turn in progress/.test(error.message)) {
    await pendingTurn.result; // drain in-flight turn, then retry once
    session.promptTurn({ prompt, ... });
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: Calling `promptTurn()` while a previous `promptTurn()` or `continueTurn()` on the same HarnessAgentSession has started and not yet finished — e.g. firing a second prompt without awaiting the first turn's `ready`/completion, prompting from a concurrent event handler, or looping prompts without awaiting the turn promise.

Common situations: Chat UIs where the user submits a new message while the agent is still streaming a reply; parallel workers sharing one session instance; missing `await` on the turn result; event-driven code that re-prompts on every stream event instead of only after turn completion.

Related errors


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