Skip to content

Migration Guide v4

Gunpal Jain edited this page Nov 15, 2026 · 4 revisions

Migrating from v3.x to v4.0

v4.0.0 mostly adds features. Most apps only need to update the package and replace model IDs that Google has retired. This page lists everything that can change how your code builds or runs.

For the full list of new features, see Release Notes v4.


1. Update the packages

All packages move to 4.0.0 together:

dotnet add package Google_GenerativeAI --version 4.0.0
dotnet add package Google_GenerativeAI.Microsoft --version 4.0.0   # if you use Microsoft.Extensions.AI
dotnet add package Google_GenerativeAI.Tools --version 4.0.0       # if you use MCP or function tools
dotnet add package Google_GenerativeAI.Live --version 4.0.0        # if you use the Live API
dotnet add package Google_GenerativeAI.Web --version 4.0.0
dotnet add package Google_GenerativeAI.Auth --version 4.0.0

Target frameworks

Package v3.6.9 v4.0.0
Google_GenerativeAI, .Auth net6.0, net7.0, net8.0, net9.0, netstandard2.0, net462 + net10.0, net11.0
Google_GenerativeAI.Microsoft, .Tools net8.0, net9.0, netstandard2.0, net462 + net10.0, net11.0
Google_GenerativeAI.Web net6.0, net7.0, net8.0, net9.0, netstandard2.0 + net10.0, net11.0
Google_GenerativeAI.Live net6.0, net7.0, net8.0, net9.0 + net10.0, net11.0

net11.0 assets are built only when the .NET 11 SDK is installed on the build machine.

Dependency versions (may affect your own package references)

Dependency v3.6.9 v4.0.0
Microsoft.Extensions.Logging / System.Text.Json 9.0.3 (net8/net9/netstandard2.0/net462) 10.0.15 on net8.0/net9.0; 11.0.0 on net10.0+, netstandard2.0, net462 (net10+ uses the in-box System.Text.Json); net6/net7 unchanged (8.x)
Microsoft.Extensions.Configuration/Options/DependencyInjection.Abstractions (Web, Live) 9.0.10 10.0.15 on net8.0/net9.0; 11.0.0 on net10.0+ and netstandard2.0; 9.0.10 on net6/net7
Microsoft.Extensions.AI.Abstractions 9.10.0 10.11.0 on net8.0/net9.0; 11.0.0 on all other targets
ModelContextProtocol / ModelContextProtocol.Core 0.4.0-preview.3 2.4.0
CSharpToJsonSchema 3.10.2-dev.69 3.10.6
Microsoft.Bcl.Memory (Tools) transitive 10.0.15 (net8/net9) / 11.0.0
Websocket.Client (Live) 5.3.0 5.5.1
Google.Apis.Auth (Auth) 1.72.0 1.78.0

What to check:

  • Microsoft.Extensions.AI: if your app references Microsoft.Extensions.AI or Microsoft.Extensions.AI.Abstractions directly, use the same major version the SDK uses for your target framework: 10.x on net8/net9, 11.x on net10+. Mixed MEAI versions cause MissingMethodException at runtime.
  • MCP: ModelContextProtocol went from a 0.4 preview to 2.x. McpTool and McpTransportFactory work as before. If you use types from the MCP SDK directly, such as McpClient, IClientTransport or StdioClientTransportOptions, check the MCP SDK's own breaking changes. McpTransportFactory.CreateHttpTransport* now also has Uri overloads; the string overloads still work.

2. Breaking changes

2.1 Subclasses of BaseModel: embedding methods take a CancellationToken

The protected virtual embedding methods gained a CancellationToken parameter. Code that calls them still compiles, because the parameter is optional. Overrides must be updated:

// v3.x
protected override Task<EmbedContentResponse> EmbedContentAsync(string model, EmbedContentRequest request) { ... }
protected override Task<BatchEmbedContentsResponse> BatchEmbedContentAsync(string model, BatchEmbedContentRequest request) { ... }

// v4.0
protected override Task<EmbedContentResponse> EmbedContentAsync(string model, EmbedContentRequest request,
    CancellationToken cancellationToken = default) { ... }
protected override Task<BatchEmbedContentsResponse> BatchEmbedContentAsync(string model, BatchEmbedContentRequest request,
    CancellationToken cancellationToken = default) { ... }

Libraries compiled against v3.x that override or call these methods must be recompiled.

2.2 Function results are sent with the user role

Gemini 3.x models reject the legacy function role with 400 INVALID_ARGUMENT. Like the official SDKs, v4 sends function results with role user:

  • FunctionCallExtensions.ToFunctionCallContent(...) now returns Content with Role = Roles.User.
  • GenerativeModel converts any Content with Role == "function" to "user" before sending. Chat histories saved by older versions keep working.
  • With Microsoft.Extensions.AI, a turn made up only of function responses still converts back to ChatRole.Tool.

If your code finds function-result turns by checking content.Role == Roles.Function, check the parts instead:

// v3.x
var isFunctionResult = content.Role == Roles.Function;

// v4.0
var isFunctionResult = content.Parts.Count > 0 && content.Parts.All(p => p.FunctionResponse != null);

2.3 Default model changed

GoogleAIModels.DefaultGeminiModel changed from models/gemini-2.5-flash to models/gemini-3.8-flash. Code that creates a model without passing one (and without GOOGLE_AI_MODEL) now calls Gemini 3.8 Flash. Pass a model explicitly if you need a specific one.

Other defaults changed to replace retired models:

API v3.x default v4.0 default
MicrosoftExtensions.AsEmbeddingGenerator(apiKey/adapter, modelName) text-embedding-004 (shut down) GoogleAIModels.GeminiEmbedding (models/gemini-embedding-001)
GenerativeAIImageGenerator(apiKey/adapter, modelName) Gemini25FlashImagePreview (shut down) GoogleAIModels.GeminiNanoBanana21

2.4 Retired model constants now produce warnings

Constants for models that Google has deprecated are marked [Obsolete(..., false)]. Using one gives compiler warning CS0618, which breaks the build if you use TreatWarningsAsErrors.

4.0.1: constants for models that Google has already shut down were removed, so code using them no longer compiles. This covers the Gemini 2.0 and old 2.5 preview models, the old embeddings, Gemma 3 on the Gemini API, every Imagen and retired Veo model, and the gecko models. The full list and replacements are in Supported Models.

Common replacements:

v3.x constant Use instead
GoogleAIModels.Gemini25Flash Gemini38Flash or Gemini35FlashLite
GoogleAIModels.Gemini25Pro Gemini38Flash or a Gemini 4 model (Gemini4Hydrogen, Gemini4Carbon, Gemini4Argon)
GoogleAIModels.Gemini2Flash / Gemini2FlashLatest Gemini38Flash
GoogleAIModels.Gemini2FlashLite Gemini35FlashLite
GoogleAIModels.Gemini3ProPreview Gemini31ProPreview
GoogleAIModels.Gemini2FlashLive001, GeminiLive25FlashPreview Gemini38Live
GoogleAIModels.Gemini25FlashImagePreview GeminiNanoBanana21
GoogleAIModels.Gemini25FlashPreviewTts / Gemini25ProPreviewTts Gemini38FlashTts
GoogleAIModels.TextEmbedding (text-embedding-004) GeminiEmbedding2 or GeminiEmbedding
GoogleAIModels.Imagen.Imagen4Generate001 (and other Imagen on the Gemini API) GeminiNanoBanana21
GoogleAIModels.Video.Veo* GoogleAIModels.Video.GeminiOmni12Flash through the Interactions API, or Veo on Vertex AI
GoogleAIModels.Aqa File Search or Vertex RAG Engine

The full table is in Supported Models. GoogleAIModels.TextEmbedding stays in SupportedEmbedingModels.All, so the SDK still accepts it, but Google's API rejects it.

2.5 Veo on the Gemini API fails fast

Google retired Veo models on the Gemini API. VideoGenerationModel now throws NotSupportedException right away on the Gemini API, without sending a request. Vertex AI is unchanged.

// v3.x - request sent, rejected by the API
var video = new VideoGenerationModel(googleAiAdapter, GoogleAIModels.Video.Veo3Generate001);

// v4.0 - use Vertex AI for Veo...
var vertexVideo = new VideoGenerationModel(vertexAdapter, VertexAIModels.Video.Veo31GeneratePreview);
// ...or Gemini Omni on the Gemini API through the Interactions API (see Interactions-API / Video-Generation)

2.6 Live API message types match the wire format

LiveServerGoAway and LiveServerSessionResumptionUpdate in v3.x used field names the Live API never sends, so those objects were always empty. The old properties still exist but are [Obsolete]:

Old (always null) New
LiveServerSessionResumptionUpdate.ResumptionToken NewHandle
LiveServerSessionResumptionUpdate.Status (SessionResumptionStatus) Resumable (bool?)
LiveServerSessionResumptionUpdate.Message (none); also new: LastConsumedClientMessageIndex
LiveServerGoAway.ErrorCode, ErrorMessage, Reconnect, RetryAfterSeconds TimeLeft (string, e.g. "30s") and TimeLeftDuration (TimeSpan?)

SessionResumptionStatus is also [Obsolete]. MultiModalLiveClient.LastSessionResumptionHandle now tracks the latest handle for you.

Live API message types renamed to match the official SDKs

The Bidi* Live API message types now use the same names as the official Google GenAI SDKs (python-genai). Only the .NET type names changed; the JSON sent over the WebSocket is identical. Rename any references in your code:

v3.x v4
BidiClientPayload LiveClientMessage
BidiGenerateContentSetup LiveClientSetup
BidiGenerateContentClientContent LiveClientContent
BidiGenerateContentRealtimeInput LiveClientRealtimeInput
BidiGenerateContentToolResponse LiveClientToolResponse
BidiGenerateContentContextUpdate LiveClientContextUpdate
BidiResponsePayload LiveServerMessage
BidiGenerateContentServerContent LiveServerContent
BidiGenerateContentSetupComplete LiveServerSetupComplete
BidiGenerateContentToolCall LiveServerToolCall
BidiGenerateContentToolCallCancellation LiveServerToolCallCancellation

The most common change is in MessageReceived handlers, where e.Payload is now a LiveServerMessage.

2.7 Parameter rename on IPlatformAdapter.GetBaseUrl

GetBaseUrl(bool appendVesion, ...) was renamed to GetBaseUrl(bool appendVersion, ...). Only callers that pass the argument by name (appendVesion: false) need to change.

2.8 apiVersion parameters are nullable

GoogleAIPlatformAdapter(..., string? apiVersion = null, ...) and VertextPlatformAdapter(..., string? apiVersion = null, ...) used to default to ApiVersions.v1Beta and ApiVersions.v1Beta1. These are still the defaults unless the new GOOGLE_GENAI_API_VERSION environment variable is set. Your source code doesn't need to change. Recompile anything that binds to these constructors. See Configuration and Error Handling.


3. Behaviour changes (no code change required)

Area v3.x v4.0
Error handling Streaming requests and file uploads threw a bare HttpRequestException. Array-shaped error bodies ([{"error":...}]) were not parsed All requests throw ApiException with ErrorCode/ErrorStatus/ErrorMessage. Array bodies are parsed, and the HTTP status is used when the body has no code. Non-Google bodies give an HttpRequestException with the status and a truncated body. If you caught HttpRequestException around streaming or uploads, also catch ApiException.
generateContent continuation Responses that Google ended early with a continuation token came back incomplete Followed automatically and merged. Turn off with GenerativeModel.EnableAutomaticContinuation = false. Limited by MaxContinuations (10)
Embedding model validation Exact string match, so gemini-embedding-001 without models/ failed Compares bare IDs: models/x, publishers/google/models/x and x all pass
Embedding cancellation EmbeddingModel ignored the CancellationToken Token passed through to the HTTP request
Vertex AI embeddings Gemini API request format sent to Vertex, so taskType, title and outputDimensionality were ignored, and text-embedding-005/gecko failed Vertex format: embedContent with embedContentConfig for Gemini models, predict for text embedding models. New Vertex-only options AutoTruncate, DocumentOcr, AudioTrackExtraction, MimeType (throw NotSupportedException on the Gemini API)
VertextPlatformAdapter(validateAccessToken: ...) Argument ignored Honoured
Vertex batch cancel BatchClient.CancelAsync called the job URL without the :cancel suffix, so jobs were not cancelled Calls {job name}:cancel
VertexRagManager.AwaitForLongRunningOperation(id, timeOut) timeOut ignored (always LongRunningOperationTimeout) timeOut honoured. Failed operations report the error code
AddGenerativeAI(GenerativeAIOptions) GOOGLE_PROJECT_ID in the environment switched to Vertex AI even when you passed only an API key An API key with no ProjectId (and no IsVertex/ExpressMode) means the Gemini API
Microsoft.Extensions.AI chat client The model's function-call turn was added once per call, which broke parallel calls. Streaming only looked for function calls in the last chunk Fixed: one model turn, and parts collected across the whole stream
RemoteFileContent (MEAI) Sent an empty file URI when the remote file had none Throws InvalidOperationException ("upload the file before referencing it")
MultiModalLiveClient Exceptions in the message handler (including your event handlers) could crash the process. Reconnects didn't re-send setup. SafetySettings were not sent Exceptions go to ErrorOccurred. Setup is re-sent after a reconnect, resuming with the last handle (ResendSetupOnReconnect, default true). SafetySettings are sent. New TurnCompleted event
Imagen through MEAI (GenerativeAIImagenGenerator) Default Imagen3Generate002 [Obsolete]: every Imagen model is retired (Vertex AI on June 30, 2026). Use GenerativeAIImageGenerator, which defaults to GeminiNanoBanana21

4. Moved to "legacy"

Google no longer documents Semantic Retrieval / AQA (SemanticRetrieverModel, CorporaManager, CorporaClient, DocumentsClient, ChunkClient, CorpusPermissionClient). The APIs still work in v4, but GoogleAIModels.Aqa is [Obsolete]. Their wiki pages are merged into Legacy Semantic Retrieval (AQA). For new work, use File Search (Gemini API) or the Vertex RAG Engine.


5. Checklist

  • Update all Google_GenerativeAI* packages to 4.0.0 together.
  • Align any direct Microsoft.Extensions.AI* and ModelContextProtocol references with the versions above.
  • Fix CS0618 warnings by moving to current model constants (Supported Models).
  • Update EmbedContentAsync/BatchEmbedContentAsync overrides to take a CancellationToken.
  • Replace Role == Roles.Function checks with checks on FunctionResponse parts.
  • Catch ApiException (not only HttpRequestException) around streaming and file uploads.
  • Move Veo calls on the Gemini API to Vertex AI or Gemini Omni, and Imagen on the Gemini API to Gemini image models.
  • Live API: read NewHandle/Resumable/TimeLeft instead of the obsolete properties.
  • Vertex AI: use region: "global" for the newest Gemini models.

Clone this wiki locally