Errors

Understand SDK errors, error codes, retry behavior, and how to handle failures safely.

The SDK provides typed errors for configuration, authentication, upstream requests, timeouts, cancellation, protocol failures, and structured output. These errors extend GeminiError and expose a code and retryable property. Some failures, such as an unavailable fetch implementation, can still produce native JavaScript errors.

Initialize the client

Configure the session cookies and XSRF token from the same signed-in Gemini Web session before making requests. The SDK does not load environment variables automatically.

src/errors.ts
import 'dotenv/config'import {  GeminiWeb,  GeminiAuthenticationError,  GeminiRateLimitError,  GeminiAbortError,  isGeminiError,} from '@orcushq/gemini' const cookies = process.env.GEMINI_COOKIESconst xsrfToken = process.env.GEMINI_XSRF_TOKEN if (!cookies?.trim() || !xsrfToken?.trim()) {  throw new Error(    'GEMINI_COOKIES and GEMINI_XSRF_TOKEN are required',  )} const clientConfig = {  model: 'gemini-3.6-flash',  cookies,  xsrfToken,} const model = new GeminiWeb(clientConfig)
.env
GEMINI_COOKIES="your_complete_cookie_header"GEMINI_XSRF_TOKEN="your_at_value"

Error Types

  • `GeminiConfigurationError` — Invalid configuration, unsupported input, an empty prompt, or an unknown model when unknownModel: "throw" is configured. Not retryable by default.
  • `GeminiAuthenticationError` — Authentication failures such as HTTP 401 or 403. Check your session cookies and authentication settings.
  • `GeminiUpstreamError` — Upstream HTTP failures, network errors, and other request failures. Retryability depends on the failure and its status.
  • `GeminiBardError` — A specific upstream error identified by a BardErrorInfo marker. Extends GeminiUpstreamError, uses code upstream, and includes bardErrorCode in its details.
  • `GeminiRateLimitError` — HTTP 429 responses. May include retryAfterMs when a retry delay is provided by the server. The supplied implementation marks this error non-retryable.
  • `GeminiTimeoutError` — A request exceeds its configured timeout. Includes timeout details and is marked non-retryable by the supplied implementation.
  • `GeminiAbortError` — A request is cancelled through an abort signal. Not retryable.
  • `GeminiProtocolError` — The response cannot be processed as expected, such as when a streaming response has no readable body or violates the expected protocol.
  • `GeminiStructuredOutputError` — Structured-output schema conversion, JSON extraction, parsing, or validation fails.

Error Properties

  • code identifies the error category using the GeminiErrorCode type.
  • retryable indicates whether the SDK retry mechanism may retry the failure. It does not guarantee that a retry will occur.
  • status contains the HTTP status when available.
  • details contains additional structured information, depending on the error.
  • cause preserves the underlying error when provided.

Retryability depends on the error constructor and the failure being mapped. Upstream HTTP 5xx responses are retryable by default, while certain statuses such as 400 and 405 are explicitly non-retryable. Authentication, rate-limit, timeout, abort, and configuration errors should not be assumed to retry automatically.

Retry Behavior

The SDK retries eligible request failures according to its retry policy. The default policy allows 3 total attempts, including the initial request, with a 2,000 ms base delay, a backoff factor of 2, and a maximum delay of 30,000 ms.

typescript
const retryingModel = new GeminiWeb({  ...clientConfig,  retry: {    attempts: 3,    delayMs: 2_000,    backoffFactor: 2,    maxDelayMs: 30_000,  },}) // Disable retries for one invocation.const response = await model.invoke('Hello', {  retry: false,}) console.log(response.content)

Retries occur only when enabled, attempts remain, and the failure is considered retryable. When a Retry-After value is available, the SDK may use it as a delay hint and clamp the delay to maxDelayMs. See Reliability.

typescript
import { DEFAULT_RETRY_POLICY } from '@orcushq/gemini' console.log(DEFAULT_RETRY_POLICY)// {//   attempts: 3,//   delayMs: 2000,//   backoffFactor: 2,//   maxDelayMs: 30000// }

Rate limits

HTTP 429 raises GeminiRateLimitError. When the upstream response provides a retry hint, retryAfterMs contains the suggested delay. Use the provided value rather than guessing a delay.

typescript
const sleep = (ms: number) =>  new Promise<void>((resolve) => setTimeout(resolve, ms)) try {  await model.invoke('Explain rate limiting.')} catch (error) {  if (error instanceof GeminiRateLimitError) {    const delayMs = error.retryAfterMs ?? 1_000     console.warn('Rate limit reached. Retry delay:', delayMs)    await sleep(delayMs)  } else {    throw error  }}

Provider-managed limits

Requests go directly to Gemini Web. Applicable quotas and rate limits depend on the provider and the authenticated session. Retries do not increase provider limits or resolve sustained overuse.

Cancellation

Pass an AbortSignal to request cancellation. You can configure a signal on the client or provide one for an individual invocation.

typescript
const controller = new AbortController() const cancellableModel = new GeminiWeb({  ...clientConfig,  signal: controller.signal,}) const timer = setTimeout(  () => controller.abort(),  5_000,) try {  await cancellableModel.invoke(    'Explain how distributed systems work.',  )} catch (error) {  if (error instanceof GeminiAbortError) {    console.log('Request cancelled.')  } else {    throw error  }} finally {  clearTimeout(timer)} // Use a separate signal for one invocation.const callController = new AbortController() await model.invoke(  'Explain request cancellation.',  { signal: callController.signal },)

A client-level signal and a per-call signal can both be configured. Handle cancellation errors in your application and verify the specific error type for the operation being cancelled.

Non-Throwing Fallbacks

Not every internal failure is propagated as an exception. For example, image-upload page-token retrieval can fall back to built-in tokens when retrieval fails. Abort-related failures are handled separately. This fallback behavior does not mean every image upload will succeed.

Model Fallback Is Not Necessarily an Error

A request can succeed even when Gemini serves a different model than requested. When the response provides sufficient evidence, the SDK reports fallback information in response metadata instead of necessarily throwing an error.

Verify the served model

If model identity matters, inspect `metadata.modelFellBack`, `metadata.fallbackReason`, `metadata.fallbackNotice`, and the requested and served model identifiers available in the response metadata.

See Served Model Evidence for details.

Error Codes

The GeminiErrorCode type defines the supported SDK error categories. Use the error class and code together when implementing application-level error handling. See the Error Codes Reference for the complete list.

Handling Errors

typescript
try {  const response = await model.invoke('Hello')  console.log(response.content)} catch (error) {  if (error instanceof GeminiAbortError) {    console.log('Request cancelled.')  } else if (error instanceof GeminiRateLimitError) {    console.warn('Rate limit reached:', error.retryAfterMs)  } else if (error instanceof GeminiAuthenticationError) {    console.error('Check Gemini session credentials.')  } else if (isGeminiError(error)) {    console.error(error.code, error.message, error.details)  } else {    // Preserve unexpected native or application errors.    throw error  }}

Use error classes or isGeminiError() to identify SDK errors. Keep a final fallback for unexpected errors, because not every failure is guaranteed to be a GeminiError.

Error Details and Security

includeErrorBody is disabled by default. Enabling it can include a truncated snippet of the upstream response body in HTTP error messages. Enable it only when needed, and avoid exposing error details or credentials in production logs.