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 before a turn starts. Fix the caller, such as by not sending
stateto a store-backed agent. - Failed turns throw
AgentErrorwithresponse,status,details,state, andsnapshotId. Resume from the last-good state or snapshot. - Foreground aborts resolve with
finishReason: 'aborted'. Let the user retry or revise the request. - Background failures appear as snapshot status
failed,aborted, orexpired. Show the status, inspect snapshot error details, and retry from a completed snapshot when possible. - Domain-level tool problems should be structured tool output 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”import { AgentError } from 'genkit/beta/client';
try { const res = await chat.send('Look up order 123.'); console.log(res.text);} catch (err) { if (err instanceof AgentError) { console.error(err.status); console.error(err.details); console.error(err.snapshotId); console.error(err.state);
const recoveryChat = err.snapshotId ? await agent.loadChat({ snapshotId: err.snapshotId }) : agent.chat({ state: err.response.raw.state });
await recoveryChat.send('Try again with order 456.'); } else { throw err; }}For streaming turns, catch errors around stream consumption and the final response. The stream rethrows failed-turn errors after yielding any available chunks.
const turn = chat.sendStream('Write a report.');
try { for await (const chunk of turn.stream) { render(chunk); }
await turn.response;} catch (err) { showFailure(err);}Tool exceptions
Section titled “Tool exceptions”Throw from a tool when the system cannot safely continue, such as a database outage, auth failure, or invariant violation.
const lookupOrder = ai.defineTool( { name: 'lookupOrder', description: 'Looks up an order by ID.', inputSchema: z.object({ orderId: z.string() }), }, async ({ orderId }) => { const order = await db.orders.find(orderId); if (!order) { throw new Error(`Order ${orderId} was not found.`); } return order; },);Return structured data when the model can recover:
return { ok: false, reason: 'ORDER_NOT_FOUND', message: 'Ask the user to check the order ID.',};Response validation
Section titled “Response validation”Call res.assertValid() when a caller requires a model message and wants blocked responses to throw.
const res = await chat.send('Write the summary.');res.assertValid();