{"record":{"id":"8644878177fb591b","repo":"vercel/ai","slug":"no-active-turn","errorCode":null,"errorMessage":"no active turn","messagePattern":"no active turn","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/harness-deepagents/src/bridge/index.ts","lineNumber":191,"sourceCode":"const responseFormatMiddleware = createMiddleware({\n  name: 'HarnessResponseFormat',\n  wrapModelCall(request, handler) {\n    return handler({\n      ...request,\n      ...(currentResponseFormat == null\n        ? {}\n        : { responseFormat: currentResponseFormat }),\n    });\n  },\n});\n\n// Host tools become LangChain tools that emit a `tool-call` and block on the host's `tool-result`.\nfunction buildHostTools(toolSchemas: StartMessage['tools']) {\n  return (toolSchemas ?? []).map(schema =>\n    tool(\n      async (input: Record<string, unknown>) => {\n        const turn = currentTurn;\n        if (!turn) throw new Error('no active turn');\n        const toolCallId = `${schema.name}-${randomUUID()}`;\n        turn.emit({\n          type: 'tool-call',\n          toolCallId,\n          toolName: schema.name,\n          input: JSON.stringify(input),\n          providerExecuted: false,\n        } as BridgeEvent);\n        const { output } = await turn.requestToolResult(toolCallId);\n        return typeof output === 'string' ? output : JSON.stringify(output);\n      },\n      {\n        name: schema.name,\n        description: schema.description ?? '',\n        schema: jsonSchemaToZodObject(schema.inputSchema),\n      },\n    ),\n  );","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-deepagents/src/bridge/index.ts#L173-L209","documentation":"Host tools are LangChain tool wrappers that emit a `tool-call` event and block waiting for the host's `tool-result` via the currently active `BridgeTurn`. If the tool body runs when `currentTurn` is undefined, there is no turn to route the call through, so the bridge throws. This is an internal lifecycle inconsistency: tools should only execute inside a turn.","triggerScenarios":"A host tool callback executes outside `runTurn`'s window — e.g. a stale agent/tool invoked after a turn completed or aborted, or tools invoked asynchronously after the turn cleared `currentTurn`.","commonSituations":"An async tool continuation racing with turn teardown; an aborted turn where the model's pending tool call still resolves; reusing a cached agent instance from a previous bridge turn in a background task.","solutions":["Ensure tool invocations originate from within an active harness turn; do not invoke host tools from background tasks or after the turn resolves.","Check for aborted turns: aborting a turn clears context, so in-flight tool calls should be cancelled via the turn's abort signal.","If reproducible, report as a bridge bug — `currentTurn` should be set whenever the agent can execute tools.","Retry the turn; transient races between turn teardown and tool completion typically resolve on a fresh turn."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await runTurn(start);\n} catch (error) {\n  if (error instanceof Error && error.message === 'no active turn') {\n    // discard stale tool call; start a fresh turn\n  }\n  throw error;\n}","preventionTips":["Never invoke host tools outside a harness turn","Honor the turn abort signal in async tool work","Don't cache agent/tool references across turns"],"tags":["lifecycle","concurrency","internal-state"],"backgroundTag":"no-active-session","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}