microsoft/semantic-kernel · error · InvalidOperationException

API key was not specified.

Error message

API key was not specified.

What it means

ModelConnectionExtensions.GetApiKeyCredential reads the 'api_key' key from the connection's ExtensionData and wraps it in an ApiKeyCredential. If the key is absent or null it throws InvalidOperationException, because no credential can be produced.

Source

Thrown at dotnet/src/Agents/OpenAI/Extensions/ModelConnectionExtensions.cs:37

    internal static Uri? TryGetEndpoint(this ModelConnection connection)
    {
        Verify.NotNull(connection);

        return connection.ExtensionData.TryGetValue("endpoint", out var value) && value is not null && value is string endpoint
            ? new Uri(endpoint)
            : null;
    }

    /// <summary>
    /// Gets the API key property as an <see cref="ApiKeyCredential"/> from the specified <see cref="ModelConnection"/>.
    /// </summary>
    /// <param name="connection">Model connection</param>
    internal static ApiKeyCredential GetApiKeyCredential(this ModelConnection connection)
    {
        Verify.NotNull(connection);

        return !connection.ExtensionData.TryGetValue("api_key", out var apiKey) || apiKey is null
            ? throw new InvalidOperationException("API key was not specified.")
            : new ApiKeyCredential(apiKey.ToString()!);
    }
}

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Ensure the connection ExtensionData contains a non-null 'api_key' entry (exact lowercase key).
  2. Load the key from configuration/environment and inject it into ExtensionData at startup.
  3. Verify secret loading (e.g., dotnet user-secrets, env vars) actually populated the value.

Example fix

// before
connection.ExtensionData["apiKey"] = key;
// after
connection.ExtensionData["api_key"] = key;
Defensive patterns

Strategy: validation

Validate before calling

if (!connection.ExtensionData.TryGetValue("api_key", out var key) || key is null)
    throw new InvalidOperationException("ModelConnection is missing a non-null 'api_key'.");

Type guard

static bool HasApiKey(ModelConnection c) =>
    c.ExtensionData.TryGetValue("api_key", out var v) && v is not null;

Try / catch

try { var cred = connection.GetApiKeyCredential(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("API key was not specified")) {
    connection.ExtensionData["api_key"] = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
}

Prevention

When it happens

Trigger: Calling GetApiKeyCredential on a ModelConnection whose ExtensionData has no 'api_key' entry, or the entry's value is null.

Common situations: Agent-definition YAML uses a different key name (e.g., 'apiKey', 'token'); api_key expected from an environment variable that was not injected; secret redaction stripped the value.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/3a26634b79ca6f17. Report an issue: GitHub.