Agent error handling
Genkit agent failures have different recovery paths depending on when they happen. A request can be rejected before an invocation starts, a turn can fail after state has been loaded, or a tool can return a domain-level result that the model can handle.
Failure categories
Section titled “Failure categories”- Init misuse throws an immediate exception (e.g.,
AgentInitErrororGenkitException) before a turn starts. Fix the parameters, such as by not sendingstateto a store-backed agent. - Failed turns throw
AgentErrorcontaining status, details, the latest snapshot ID, and the recoverable last-good state. - Background/detached failures appear as snapshot status
failed,aborted, orexpired. Inspect the snapshot’s error property and retry from the last-known completed snapshot. - Tool domain problems should return structured tool outputs when the model can recover. Let the model explain the issue or ask the user for corrected input.
Handle failed turns
Section titled “Handle failed turns”try { final res = await chat.send(text: 'Look up order 123.'); print(res.text);} on AgentError catch (err) { print('Turn failed: ${err.status}'); print('Error details: ${err.message}');
// Recover the conversation: final recoveryChat = err.snapshotId != null ? await agent.loadChat(snapshotId: err.snapshotId!) : agent.chat(state: err.state);
await recoveryChat.send(text: 'Try again with order 456.');}For streaming turns, catch errors around the chunk stream consumption and the final response Future. The stream rethrows failed-turn errors after yielding any chunks that arrived before the failure occurred.
final turn = chat.sendStream(text: 'Write a long report.');
try { await for (final chunk in turn.stream) { render(chunk); } await turn.response;} on AgentError catch (err) { showFailure(err);}Tool exceptions
Section titled “Tool exceptions”Throw an exception from a tool when the system cannot safely proceed, such as a database outage or auth failure:
final lookupOrder = ai.defineTool( name: 'lookupOrder', description: 'Looks up an order by ID.', inputSchema: LookupOrderInput.$schema, outputSchema: Order.$schema, fn: (input, _) async { final order = await db.orders.find(input.orderId); if (order == null) { throw Exception('Order ${input.orderId} was not found.'); } return order; },);When the error is soft and the model has a chance to recover (e.g. invalid user input), return structured output:
if (order == null) { return { 'ok': false, 'reason': 'ORDER_NOT_FOUND', 'message': 'Ask the user to check the order ID.', };}