Skip to content

Configuration and Error Handling

Gunpal Jain edited this page Nov 15, 2026 · 1 revision

Configuration and Error Handling

This page covers the environment variables the SDK reads, Vertex AI locations, HttpClient and ILogger injection, timeouts, and the exceptions the SDK throws.


Environment variables

The SDK reads these variables through the GenerativeAI.EnvironmentVariables class. A value you pass in code always wins over the environment variable.

Variable Used for Default
GOOGLE_API_KEY Gemini API key. GoogleAIPlatformAdapter uses it when you pass null. VertextPlatformAdapter uses it as the Vertex AI Express key. LiveMusicClient(apiKey: null) also uses it none
GOOGLE_AI_MODEL Model used when none is passed (GenerativeModel, VertexAIModel, AddGenerativeAI()) GoogleAIModels.DefaultGeminiModel (models/gemini-3.8-flash)
GOOGLE_PROJECT_ID Vertex AI project ID. With AddGenerativeAI(), setting it also switches the default to Vertex AI read from the credentials file
GOOGLE_REGION Vertex AI location us-central1
GOOGLE_ACCESS_TOKEN OAuth access token for Vertex AI none
GOOGLE_APPLICATION_CREDENTIALS Path to a service account or ADC JSON file (Vertex AI) %APPDATA%/gcloud/application_default_credentials.json
GOOGLE_WEB_CREDENTIALS Path to OAuth web credentials. Vertex AI checks it before GOOGLE_APPLICATION_CREDENTIALS none
GOOGLE_GENAI_API_VERSION New in v4. The default API version when none is passed. beta means v1beta on the Gemini API and v1beta1 on Vertex AI. Any other value, such as v1, is used as written v1beta (Gemini API) / v1beta1 (Vertex AI)

Notes:

  • The SDK reads GOOGLE_GENAI_API_VERSION every time it creates a platform adapter. It reads the other variables once, when the app starts (they are static readonly fields).
  • GOOGLE_GENAI_API_VERSION only applies when the API version is left as null. The GoogleAIPlatformAdapter and VertextPlatformAdapter constructors now take string? apiVersion = null, and so do GoogleAi, GenerativeModel(apiKey, ...) and VertexAIModel. The VertexAI(...) convenience constructor still defaults apiVersion to ApiVersions.v1Beta1, so it ignores the variable unless you pass apiVersion: null.
  • The defaults stay on the beta versions because previews, the Live API and TTS are only on v1beta.
  • ApiVersions has v1, v1Beta, v1Beta1, and the new v1Alpha. Ephemeral Live API auth tokens use v1Alpha.
// Pin the API version in code
var adapter = new GoogleAIPlatformAdapter(apiKey, apiVersion: ApiVersions.v1);

// Or for the whole process
Environment.SetEnvironmentVariable("GOOGLE_GENAI_API_VERSION", "v1");
var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini38Flash); // uses v1

ASP.NET Core (Google_GenerativeAI.Web)

AddGenerativeAI() fills any option you didn't set from the variables above. Here is how it decides between the Gemini API and Vertex AI:

  • AddGenerativeAI() and AddGenerativeAI(IConfiguration): if IsVertex isn't set, the app uses Vertex AI when GOOGLE_PROJECT_ID is set.
  • AddGenerativeAI(GenerativeAIOptions): changed in v4. If you pass an API key (Credentials.ApiKey) but no ProjectId, leave IsVertex unset and don't enable ExpressMode, the app now uses the Gemini API, even when GOOGLE_PROJECT_ID is set. Set IsVertex to choose explicitly.

See Web Application Integration.


Vertex AI locations

The location (region) decides which endpoint the SDK calls:

Region Base URL
global https://aiplatform.googleapis.com/{version}/projects/{project}/locations/global/...
any other, for example us-central1 https://{region}-aiplatform.googleapis.com/{version}/projects/{project}/locations/{region}/...
Express mode BaseUrls.VertexAIExpress (API key, no project or location)

Google serves the newest Gemini models (Gemini 4, 3.x) on Vertex AI from the global location. Some services are only available in regional locations, such as the RAG Engine and some tuning or batch features. For those, use a regional location such as us-central1.

var vertex = new VertexAI(projectId: "my-project", region: "global");
// or: set GOOGLE_REGION=global

HttpClient, logging and timeouts

Every client and model accepts an optional HttpClient and an optional Microsoft.Extensions.Logging.ILogger:

using var http = new HttpClient { Timeout = TimeSpan.FromMinutes(10) };
ILogger logger = loggerFactory.CreateLogger("Gemini");

var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini38Flash, httpClient: http, logger: logger);

var googleAi = new GoogleAi(apiKey, client: http, logger: logger); // models/clients it creates share http + logger
var files = new FileClient(new GoogleAIPlatformAdapter(apiKey, logger: logger), http, logger);
  • If you don't pass an HttpClient, each client creates its own, with a 5-minute timeout and User-Agent: Google_GenerativeAI SDK. In long-running apps, pass a shared or IHttpClientFactory-managed client.
  • The logger receives non-success status codes (URLs have the API key masked) and, for some clients, request diagnostics. Platform adapters also take a logger parameter.
  • Cancellation: every async method takes a CancellationToken. In v4, embedding calls pass it all the way to the HTTP request. Before v4, EmbedContentAsync/BatchEmbedContentAsync ignored it.
  • Long-running operations: VertexRagManager.LongRunningOperationTimeout defaults to 5 minutes, and AwaitForLongRunningOperation(operationId, timeOut, ...) now honours the timeOut (milliseconds) you pass. Several clients, such as Interactions, File Search, Tuning and Triggers, have WaitFor...Async helpers with their own poll interval and timeout parameters.
  • Retries: the SDK doesn't retry failed HTTP requests on its own. To retry on 429 or 5xx, add a policy to the HttpClient you pass, for example Microsoft.Extensions.Http.Resilience or Polly. Some features have their own recovery logic, listed below.

Automatic recovery features (v4)

Feature Setting Default
generateContent continuation tokens: when Google ends a response early (FinishReason.CONTINUATION), the SDK re-sends the request with the token and merges the results. Streams continue the same way, including after a dropped stream that had reached a checkpoint GenerativeModel.EnableAutomaticContinuation, GenerativeModel.MaxContinuations true, 10
Interactions continuation (requires_continuation) InteractionsClient.EnableAutomaticContinuation, MaxContinuations true, 10
Resuming a dropped Interactions stream from the last event InteractionsClient.MaxStreamReconnects 3
Live API: re-send setup (and resume the session) after the WebSocket reconnects MultiModalLiveClient.ResendSetupOnReconnect true
var model = new GenerativeModel(apiKey, GoogleAIModels.Gemini38Flash)
{
    EnableAutomaticContinuation = false // receive the partial response and token yourself
};

Exceptions

All exception types are in the GenerativeAI.Exceptions namespace.

Exception When it's thrown Useful members
ApiException Google returned an error response that the SDK could parse (any non-2xx with a Google error body) ErrorCode (int, usually the HTTP or RPC code), ErrorStatus (for example INVALID_ARGUMENT, RESOURCE_EXHAUSTED), ErrorMessage; Message is "{status} (Code: {code}): {message}"
HttpRequestException A non-2xx response with a body that isn't a Google error (for example HTML from a proxy). In v4 the message includes the status code and up to 500 characters of the body Message
VertexAIException A Vertex AI long-running operation, for example a RAG Engine import or corpus operation, finished with an error Status (GoogleRpcStatus with Code, Message, Details)
GenerativeAIException SDK-side failures: a response blocked by safety filters (the block reason is in Details), a call to a function the model doesn't know (unless FunctionCallingBehaviour.AutoHandleBadFunctionCalls is on), a failed file or File Search operation, or a missing authenticator for the corpus manager Message, Details
FileTooLargeException A file is bigger than the upload limit Message
NotSupportedException You called a feature the current platform doesn't support. Examples: Veo on the Gemini API, WebhookConfig on Vertex AI batch jobs, Vertex-only embedding options on the Gemini API, an unsupported embedding model Message explains the alternative
ArgumentException / ArgumentNullException Missing required arguments, for example no API key for the Gemini API

How the SDK parses error responses (v4)

When a request fails, ApiBase reads the response body and tries to turn it into an ApiException:

  1. It accepts both {"error": {...}} and the array form [{"error": {...}}]. Some endpoints return the array form, for example 402 prepayment errors.
  2. It needs error.message. It takes error.code when the code is numeric and otherwise uses the HTTP status code. It uses error.status when present, or "Unknown status".
  3. If the body is empty, isn't JSON, or has no error.message, the SDK throws HttpRequestException with the status code and a truncated body.

In v4 the same handling applies to all requests, including streaming (StreamContentAsync) and file uploads. In v3.x those threw a bare HttpRequestException (from EnsureSuccessStatusCode) with no Google details.

using GenerativeAI.Exceptions;

try
{
    var response = await model.GenerateContentAsync("Hello");
    Console.WriteLine(response.Text());
}
catch (ApiException ex) when (ex.ErrorCode == 429 || ex.ErrorStatus == "RESOURCE_EXHAUSTED")
{
    // quota or rate limit: back off and retry
}
catch (ApiException ex) when (ex.ErrorStatus == "INVALID_ARGUMENT")
{
    Console.WriteLine($"Bad request: {ex.ErrorMessage}");
}
catch (ApiException ex)
{
    Console.WriteLine($"{ex.ErrorStatus} ({ex.ErrorCode}): {ex.ErrorMessage}");
}
catch (HttpRequestException ex)
{
    // non-Google error body (proxy, network appliance, etc.)
    Console.WriteLine(ex.Message);
}

Live API errors

MultiModalLiveClient reports errors through the ErrorOccurred event instead of throwing on the WebSocket thread. In v4, exceptions thrown inside your own event handlers are caught and reported there as well, so they no longer crash the process. A GoAwayReceived event means the server will close the connection soon. Its LiveServerGoAway.TimeLeft / TimeLeftDuration tells you how long you have. See Multimodal Live API.

Clone this wiki locally