microsoft/semantic-kernel · critical · InvalidOperationException

Please provide a valid OpenAI:ApiKey to run this sample. See

Error message

Please provide a valid OpenAI:ApiKey to run this sample. See the associated README.md for more details.

What it means

MCPServer's GetConfiguration builds config from user secrets + env vars and throws InvalidOperationException if OpenAI:ApiKey is absent. EmbeddingModelId and ChatModelId have defaults (text-embedding-3-small, gpt-4o-mini), but the API key is mandatory. The message is written to stderr first, then thrown.

Source

Thrown at dotnet/samples/Demos/ModelContextProtocolClientServer/MCPServer/Program.cs:74

await builder.Build().RunAsync();

/// <summary>
/// Gets configuration.
/// </summary>
static (string EmbeddingModelId, string ChatModelId, string ApiKey) GetConfiguration()
{
    // Load and validate configuration
    IConfigurationRoot config = new ConfigurationBuilder()
        .AddUserSecrets<Program>()
        .AddEnvironmentVariables()
        .Build();

    if (config["OpenAI:ApiKey"] is not { } apiKey)
    {
        const string Message = "Please provide a valid OpenAI:ApiKey to run this sample. See the associated README.md for more details.";
        Console.Error.WriteLine(Message);
        throw new InvalidOperationException(Message);
    }

    string embeddingModelId = config["OpenAI:EmbeddingModelId"] ?? "text-embedding-3-small";

    string chatModelId = config["OpenAI:ChatModelId"] ?? "gpt-4o-mini";

    return (embeddingModelId, chatModelId, apiKey);
}
static ResourceTemplateDefinition CreateVectorStoreSearchResourceTemplate(Kernel? kernel = null)
{
    return new ResourceTemplateDefinition
    {
        Kernel = kernel,
        ResourceTemplate = new()
        {
            UriTemplate = "vectorStore://{collection}/{prompt}",
            Name = "Vector Store Record Retrieval",
            Description = "Retrieves relevant records from the vector store based on the provided prompt."

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. dotnet user-secrets set OpenAI:ApiKey <key>.
  2. Or export OPENAI__ApiKey (and optionally OPENAI__EmbeddingModelId / OPENAI__ChatModelId) env vars.
  3. Verify the user-secrets ID matches this MCPServer project.
  4. Confirm the key is valid for the models you reference.

Example fix

// before
if (config["OpenAI:ApiKey"] is not { } apiKey)
{
    const string Message = "Please provide a valid OpenAI:ApiKey to run this sample...";
    Console.Error.WriteLine(Message);
    throw new InvalidOperationException(Message);
}

// after (user secret)
// dotnet user-secrets set OpenAI:ApiKey sk-...
// dotnet user-secrets set OpenAI:ChatModelId gpt-4o
// dotnet user-secrets set OpenAI:EmbeddingModelId text-embedding-3-small
Defensive patterns

Strategy: validation

Validate before calling

if (config["OpenAI:ApiKey"] is not { } apiKey)
    throw new InvalidOperationException(
        "Set OpenAI:ApiKey via user secrets or OPENAI__ApiKey env var.");

Type guard

static bool HasOpenAiKey(IConfigurationRoot c) =>
    !string.IsNullOrEmpty(c["OpenAI:ApiKey"]);

Prevention

When it happens

Trigger: config["OpenAI:ApiKey"] is null after merging user secrets and environment variables.

Common situations: Server run without user secrets set, OPENAI__ApiKey not exported, or the user-secrets ID bound to a different assembly.

Related errors


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