{"record":{"id":"7832992a454bf8fd","repo":"vercel/ai","slug":"harness-session-this-sessionid-already-has-a-t","errorCode":null,"errorMessage":"`Harness session ${this.sessionId} already has a turn in progress.`","messagePattern":"`Harness session (.+?) already has a turn in progress\\.`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/harness/src/agent/harness-agent-session.ts","lineNumber":642,"sourceCode":"  }\n\n  private toResumeStateWithContinuation(options: {\n    continueFrom: HarnessAgentContinueTurnState;\n  }): HarnessAgentResumeSessionState {\n    const { continueFrom } = options;\n    return {\n      type: 'resume-session',\n      harnessId: continueFrom.harnessId,\n      specificationVersion: continueFrom.specificationVersion,\n      data: continueFrom.data,\n      continueFrom,\n    };\n  }\n\n  private requirePromptableTurn(): void {\n    if (this.turnState === 'idle') return;\n    if (this.turnState === 'running') {\n      throw new Error(\n        `Harness session ${this.sessionId} already has a turn in progress.`,\n      );\n    }\n    throw new Error(\n      `Harness session ${this.sessionId} has an unfinished turn and must be continued before accepting a new prompt.`,\n    );\n  }\n\n  private requireContinuableTurn(): void {\n    if (\n      this.turnState === 'awaiting-approval' ||\n      this.turnState === 'awaiting-tool-result' ||\n      this.turnState === 'suspended'\n    ) {\n      return;\n    }\n    if (this.turnState === 'running') {\n      throw new Error(","sourceCodeStart":624,"sourceCodeEnd":660,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness/src/agent/harness-agent-session.ts#L624-L660","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Await the in-flight turn's result (including its `ready` promise) before calling `promptTurn()` again.","Serialize prompts: queue incoming prompts and process them one at a time per session, or create a separate session per concurrent task.","Abort or suspend the running turn first (via the turn's prompt control / abortSignal, or `suspendTurn()`) before issuing a new prompt.","Check `session.hasUnfinishedTurn()` and skip/queue the new prompt when it returns true."],"exampleFix":"// before\nsession.promptTurn({ prompt, ... }); // not awaited\nsession.promptTurn({ prompt2, ... }); // throws: turn already in progress\n\n// after\nconst turn = session.promptTurn({ prompt, ... });\nawait turn.ready;            // wait for the turn to settle\nawait turn.result;           // then start the next prompt\nsession.promptTurn({ prompt2, ... });","handlingStrategy":"validation","validationCode":"if (session.hasUnfinishedTurn()) {\n  throw new TurnBusyError(); // queue or await the in-flight turn first\n}","typeGuard":null,"tryCatchPattern":"try {\n  session.promptTurn({ prompt, ... });\n} catch (error) {\n  if (error instanceof Error && /already has a turn in progress/.test(error.message)) {\n    await pendingTurn.result; // drain in-flight turn, then retry once\n    session.promptTurn({ prompt, ... });\n  } else {\n    throw error;\n  }\n}","preventionTips":["Await each turn's `ready` promise and result before prompting again.","Keep one prompt in flight per session; queue concurrent user inputs.","Always await turn promises — missing `await` is the top cause.","Use one session per concurrent worker instead of sharing."],"tags":["concurrency","lifecycle","state-machine","harness"],"backgroundTag":"concurrent-operation-not-allowed","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}