G
YouTube TikTok Games
Skip to content

Error types

Genkit knows about two specialized types: GenkitError and UserFacingError. GenkitError is intended for use by Genkit itself or Genkit plugins. UserFacingError is intended for ContextProviders and your code. The separation between these two error types helps you better understand where your error is coming from.

Genkit plugins for web hosting (e.g. @genkit-ai/express or @genkit-ai/next) SHOULD capture all other Error types and instead report them as an internal error in the response. This adds a layer of security to your application by ensuring that internal details of your application do not leak to attackers.

Get failures on the response with throwOnError: false

Section titled “Get failures on the response with throwOnError: false”

By default, generate() throws when something fails: a model error, a tool error, a blocked response, output that does not match the schema, or the maxTurns limit. In a tool loop that throws away the rounds that already finished.

Set throwOnError: false to get the failure back on the response instead, together with the conversation up to the last completed tool round. You can then retry from there without repeating the tool calls that already ran:

const opts = {
model: googleAI.model('gemini-flash-latest'),
tools: [getWeather],
throwOnError: false,
};
let res = await ai.generate({ ...opts, prompt: 'What should I wear in Tokyo today?' });
if (res.error) {
console.warn(res.finishReason, res.error.status, res.error.message);
if (res.finishReason === 'failed' || res.finishReason === 'aborted') {
// res.messages ends at a turn seam, so it is safe to send again.
res = await ai.generate({ ...opts, messages: res.messages });
}
}

A response that reports a failure works like this:

  • error holds the classified failure: a status (such as INTERNAL), a message, and the original error’s details. Check error, not finishReason, to tell whether the call failed.
  • finishReason is failed when something broke (a model call, a tool, a middleware hook) and aborted when the caller stopped the loop: the abortSignal fired, the model call rejected with an AbortError or TimeoutError, or maxTurns was reached. A provider that answers with a status such as DEADLINE_EXCEEDED or ABORTED still reports failed.
  • A failed or aborted response has no message, so text is empty and output is null. Its finishMessage has the same text as error.message.
  • Other failures keep the model’s own finish reason and finish message beside error: a blocked response (blocked, with FAILED_PRECONDITION), a response without a message, and output that fails schema validation (usually stop, with INVALID_ARGUMENT, and the model’s message so you can inspect the raw text). A resume whose restarted tool interrupts again keeps interrupted; answer it with resume. Don’t send these responses’ messages again as they are.
  • For a failed or aborted response, messages never ends on a tool request that nothing answered, because no provider accepts that. A failed tool discards the whole round it was part of, and is reported as INTERNAL with a message that starts with tool "<name>" failed: followed by the tool’s error text. If the abortSignal had fired, it is reported as CANCELLED (tool "<name>" stopped: ...) with finishReason aborted instead.
  • Text streamed before the failure has already reached onChunk.

Errors that happen before the request is resolved, such as an unknown model, tool, or resource, invalid options, or a generate middleware hook that fails before the first turn runs, still throw, because there is no response to return.

Code that does not set throwOnError gets the same errors as before. Agents use the same mechanism to save failed turns as resume points; see Agent error handling.