{"record":{"id":"00e4ce3bc2edce3f","repo":"microsoft/aspire","slug":"the-api-key-parameter-must-be-marked-as-secret-use","errorCode":null,"errorMessage":"The API key parameter must be marked as secret. Use AddParameter with secret: true when creating the parameter.","messagePattern":"The API key parameter must be marked as secret\\. Use AddParameter with secret: true when creating the parameter\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.OpenAI/OpenAIExtensions.cs","lineNumber":167,"sourceCode":"        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrEmpty(endpoint);\n\n        builder.Resource.Endpoint = endpoint;\n        return builder;\n    }\n\n    /// <summary>\n    /// Configures the API key for the OpenAI parent resource from a parameter.\n    /// </summary>\n    [AspireExport]\n    public static IResourceBuilder<OpenAIResource> WithApiKey(this IResourceBuilder<OpenAIResource> builder, IResourceBuilder<ParameterResource> apiKey)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentNullException.ThrowIfNull(apiKey);\n\n        if (!apiKey.Resource.Secret)\n        {\n            throw new ArgumentException(\"The API key parameter must be marked as secret. Use AddParameter with secret: true when creating the parameter.\", nameof(apiKey));\n        }\n\n        // Remove the existing parameter if it's the default one\n        if (builder.Resource.DefaultKeyParameter == builder.Resource.Key)\n        {\n            builder.ApplicationBuilder.Resources.Remove(builder.Resource.Key);\n        }\n\n        builder.Resource.Key = apiKey.Resource;\n\n        return builder;\n    }\n\n    /// <summary>\n    /// Adds a health check to the OpenAI Model resource.\n    /// </summary>\n    /// <param name=\"builder\">The resource builder.</param>\n    /// <returns>The resource builder.</returns>","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.OpenAI/OpenAIExtensions.cs#L149-L185","documentation":"WithApiKey validates that the IResourceBuilder<IResourceWithParameter> passed as apiKey was created as a secret parameter (parameter resource's Secret flag). Passing a non-secret parameter would cause the API key to be emitted as plain configuration instead of a secret, so the method throws ArgumentException immediately. This is an explicit API contract check.","triggerScenarios":"Calling openai.WithApiKey(builder.AddParameter(\"my-key\")) (secret defaults to false) or WithApiKey over a parameter created by another library call that did not pass secret: true.","commonSituations":"Copying a parameter declaration from non-secret examples; sharing a parameter between a secret and non-secret consumer; refactoring where secret: true was dropped.","solutions":["Change the parameter creation to builder.AddParameter(\"my-key\", secret: true) before passing it to WithApiKey.","Verify the resource passed to WithApiKey is the parameter resource, not another resource.","If the parameter is shared, create a dedicated secret parameter for the API key."],"exampleFix":"// before\nvar key = builder.AddParameter(\"openai-key\");\nvar openai = builder.AddOpenAI(\"openai\").WithApiKey(key);\n// after\nvar key = builder.AddParameter(\"openai-key\", secret: true);\nvar openai = builder.AddOpenAI(\"openai\").WithApiKey(key);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"bool IsValidApiKeyParameter(IResourceBuilder<IResourceWithParameter> b) => b.Resource is IResourceWithParameter { } r &&\n    ((IValueProvider)r is { } || true) && GetSecretFlag(r);\n// simplest: check before calling\n// if (!apiKey.Resource.Secret) throw before invoking WithApiKey","tryCatchPattern":"try { openai.WithApiKey(apiKey); } catch (ArgumentException ex) { /* re-create parameter with secret: true */ }","preventionTips":["Always create API key parameters with AddParameter(name, secret: true)","Centralize secret-parameter creation in a helper to avoid drift","Review parameter declarations when sharing them between resources"],"tags":["aspire","openai","secret","parameter"],"backgroundTag":"invalid-argument-value","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}