{"record":{"id":"3d3b1bc863c450eb","repo":"microsoft/semantic-kernel","slug":"maxtokens-maxtokens-is-not-valid-the-value-must","errorCode":null,"errorMessage":"MaxTokens {maxTokens} is not valid, the value must be greater than zero","messagePattern":"MaxTokens (.+?) is not valid, the value must be greater than zero","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Connectors/Connectors.Google/Core/ClientBase.cs","lineNumber":51,"sourceCode":"\n    protected ClientBase(\n        HttpClient httpClient,\n        ILogger? logger,\n        string? apiKey = null)\n    {\n        Verify.NotNull(httpClient);\n\n        this.HttpClient = httpClient;\n        this.Logger = logger ?? NullLogger.Instance;\n        this._apiKey = apiKey;\n    }\n\n    protected static void ValidateMaxTokens(int? maxTokens)\n    {\n        // If maxTokens is null, it means that the user wants to use the default model value\n        if (maxTokens is < 1)\n        {\n            throw new ArgumentException($\"MaxTokens {maxTokens} is not valid, the value must be greater than zero\");\n        }\n    }\n\n    protected async Task<string> SendRequestAndGetStringBodyAsync(\n        HttpRequestMessage httpRequestMessage,\n        CancellationToken cancellationToken)\n    {\n        using var response = await this.HttpClient.SendWithSuccessCheckAsync(httpRequestMessage, cancellationToken)\n            .ConfigureAwait(false);\n        var body = await response.Content.ReadAsStringWithExceptionMappingAsync(cancellationToken)\n            .ConfigureAwait(false);\n        return body;\n    }\n\n    protected async Task<HttpResponseMessage> SendRequestAndGetResponseImmediatelyAfterHeadersReadAsync(\n        HttpRequestMessage httpRequestMessage,\n        CancellationToken cancellationToken)\n    {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Connectors/Connectors.Google/Core/ClientBase.cs#L33-L69","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — 0 means 'no limit' in caller logic but throws\nsettings.MaxTokens = remainingTokens; // remainingTokens can be 0\n\n// after — null means 'use model default'\nsettings.MaxTokens = remainingTokens > 0 ? remainingTokens : null;","handlingStrategy":"validation","validationCode":"if (settings.MaxTokens is int tokens && tokens < 1)\n{\n    throw new ArgumentOutOfRangeException(nameof(settings.MaxTokens),\n        $\"MaxTokens must be >= 1 or null (for model default). Got {tokens}.\");\n}\n// or normalize:\nsettings.MaxTokens = settings.MaxTokens switch\n{\n    null => null,           // use model default\n    < 1 => null,            // treat invalid as default\n    var v => v              // valid value\n};","typeGuard":"static bool IsValidMaxTokens(int? maxTokens) => maxTokens is null or >= 1;","tryCatchPattern":"try { var result = await client.GetChatMessageContentsAsync(history, settings); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"MaxTokens\"))\n{\n    logger.LogWarning(\"Invalid MaxTokens {Val}, retrying with default\", settings.MaxTokens);\n    settings.MaxTokens = null;\n    result = await client.GetChatMessageContentsAsync(history, settings);\n}","preventionTips":["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."],"tags":["google","gemini","configuration","validation","max-tokens"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}