microsoft/semantic-kernel · error · ArgumentException
MaxTokens {maxTokens} is not valid, the value must be greate
Error message
MaxTokens {maxTokens} is not valid, the value must be greater than zero What it means
Thrown by ClientBase.ValidateMaxTokens when the maxTokens value is a non-null integer less than 1. The pattern match 'maxTokens is < 1' only fires for non-null values (nullable int), so null is explicitly allowed and means 'use the model default'. A value of 0 or any negative integer is rejected because it is meaningless as a token budget.
Source
Thrown at dotnet/src/Connectors/Connectors.Google/Core/ClientBase.cs:51
protected ClientBase(
HttpClient httpClient,
ILogger? logger,
string? apiKey = null)
{
Verify.NotNull(httpClient);
this.HttpClient = httpClient;
this.Logger = logger ?? NullLogger.Instance;
this._apiKey = apiKey;
}
protected static void ValidateMaxTokens(int? maxTokens)
{
// If maxTokens is null, it means that the user wants to use the default model value
if (maxTokens is < 1)
{
throw new ArgumentException($"MaxTokens {maxTokens} is not valid, the value must be greater than zero");
}
}
protected async Task<string> SendRequestAndGetStringBodyAsync(
HttpRequestMessage httpRequestMessage,
CancellationToken cancellationToken)
{
using var response = await this.HttpClient.SendWithSuccessCheckAsync(httpRequestMessage, cancellationToken)
.ConfigureAwait(false);
var body = await response.Content.ReadAsStringWithExceptionMappingAsync(cancellationToken)
.ConfigureAwait(false);
return body;
}
protected async Task<HttpResponseMessage> SendRequestAndGetResponseImmediatelyAfterHeadersReadAsync(
HttpRequestMessage httpRequestMessage,
CancellationToken cancellationToken)
{View on GitHub (pinned to c028a0c7dc)
Solutions
- Set MaxTokens to null instead of 0 to use the model's default maximum output: settings.MaxTokens = null;
- Ensure any computed token budget is clamped to at least 1: settings.MaxTokens = Math.Max(1, budget);
- Validate before the call: if (settings.MaxTokens is int v && v < 1) throw or set to null.
- Do not use 0 as a sentinel for 'no limit' — use null.
Example fix
// before — 0 means 'no limit' in caller logic but throws settings.MaxTokens = remainingTokens; // remainingTokens can be 0 // after — null means 'use model default' settings.MaxTokens = remainingTokens > 0 ? remainingTokens : null;
Defensive patterns
Strategy: validation
Validate before calling
if (settings.MaxTokens is int tokens && tokens < 1)
{
throw new ArgumentOutOfRangeException(nameof(settings.MaxTokens),
$"MaxTokens must be >= 1 or null (for model default). Got {tokens}.");
}
// or normalize:
settings.MaxTokens = settings.MaxTokens switch
{
null => null, // use model default
< 1 => null, // treat invalid as default
var v => v // valid value
}; Type guard
static bool IsValidMaxTokens(int? maxTokens) => maxTokens is null or >= 1;
Try / catch
try { var result = await client.GetChatMessageContentsAsync(history, settings); }
catch (ArgumentException ex) when (ex.Message.Contains("MaxTokens"))
{
logger.LogWarning("Invalid MaxTokens {Val}, retrying with default", settings.MaxTokens);
settings.MaxTokens = null;
result = await client.GetChatMessageContentsAsync(history, settings);
} Prevention
- Use null for MaxTokens to mean 'model default' — never use 0 as a sentinel.
- Clamp computed token budgets: settings.MaxTokens = Math.Max(1, budget).
- Validate MaxTokens in settings validation when loading from user input or configuration.
When it happens
Trigger: Setting GeminiPromptExecutionSettings.MaxTokens to 0 or a negative number. The validation runs during request construction (CreateGeminiRequest and similar paths), not at property-set time. Any Google/Gemini connector call path that builds a request invokes this check.
Common situations: Computing MaxTokens dynamically (e.g. maxLength - currentTokens) and hitting a zero or negative result. Defaulting MaxTokens to 0 in a configuration object meaning 'unlimited' when the connector expects null for that. Passing a count from a UI input that was left at 0. Using the same settings object across providers where 0 means 'no limit' in one but is invalid here.
Related errors
- Auto-invocation of tool calls may only be used with a {nameo
- Chat history can't contain only system messages.
- GeminiPart is invalid. One and only one property among Text,
- Image content does not contain any data or uri.
- Image content MimeType is empty.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/3d3b1bc863c450eb.
Report an issue: GitHub.