{"record":{"id":"fd8b885f83b1be30","repo":"microsoft/aspire","slug":"azure-cognitive-services-project-resource-builder-resource","errorCode":null,"errorMessage":"Azure Cognitive Services project resource '{builder.Resource.Name}' already has a Key Vault connection configured.","messagePattern":"Azure Cognitive Services project resource '(.+?)' already has a Key Vault connection configured\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Foundry/Project/ProjectBuilderExtension.cs","lineNumber":99,"sourceCode":"\n    /// <summary>\n    /// Adds a Key Vault connection to the Microsoft Foundry project.\n    /// </summary>\n    /// <param name=\"builder\">The resource builder for the Microsoft Foundry project.</param>\n    /// <param name=\"keyVault\">The Key Vault resource to associate with the project.</param>\n    /// <returns>A reference to the <see cref=\"IResourceBuilder{T}\"/> for chaining.</returns>\n    /// <ats-returns>The resource builder.</ats-returns>\n    /// <exception cref=\"InvalidOperationException\">Thrown when the project already has a Key Vault connection configured.</exception>\n    [AspireExport]\n    public static IResourceBuilder<AzureCognitiveServicesProjectResource> WithKeyVault(\n        this IResourceBuilder<AzureCognitiveServicesProjectResource> builder,\n        IResourceBuilder<AzureKeyVaultResource> keyVault)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentNullException.ThrowIfNull(keyVault);\n        if (builder.Resource.KeyVaultConn is not null)\n        {\n            throw new InvalidOperationException($\"Azure Cognitive Services project resource '{builder.Resource.Name}' already has a Key Vault connection configured.\");\n        }\n\n        var conn = builder.AddConnection(keyVault);\n        // We need to keep a reference to the connection resource for dependency tracking\n        builder.Resource.KeyVaultConn = conn.Resource;\n        return builder.WithRoleAssignments(keyVault, KeyVaultBuiltInRole.KeyVaultSecretsOfficer);\n    }\n\n    /// <summary>\n    /// Adds an Application Insights resource to the Microsoft Foundry project,\n    /// overriding the default (which is to create a new Application Insights resource).\n    /// </summary>\n    /// <param name=\"builder\">The resource builder for the Microsoft Foundry project.</param>\n    /// <param name=\"appInsights\">The Application Insights resource to associate with the project.</param>\n    /// <returns>A reference to the <see cref=\"IResourceBuilder{T}\"/> for chaining.</returns>\n    /// <ats-returns>The resource builder.</ats-returns>\n    [AspireExport]\n    public static IResourceBuilder<AzureCognitiveServicesProjectResource> WithAppInsights(","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Foundry/Project/ProjectBuilderExtension.cs#L81-L117","documentation":"WithKeyVault() attaches a Key Vault connection to an Azure Cognitive Services (Foundry) project resource and assigns the Key Vault Secrets Officer role. The library throws this InvalidOperationException when the project resource already has a KeyVaultConn configured, because only one Key Vault connection per project is supported.","triggerScenarios":"Calling WithKeyVault() twice on the same IResourceBuilder<AzureCognitiveServicesProjectResource>, e.g. in a shared extension method that also calls it, or copy-pasting configuration blocks that each attach a Key Vault.","commonSituations":"Refactoring AppHost code where WithKeyVault was moved but not removed from the old location; conditionally configuring Key Vault in multiple helper methods; merging two AppHost configuration branches that both call WithKeyVault.","solutions":["Remove the duplicate WithKeyVault() call so it runs only once per project resource","Check builder.Resource.KeyVaultConn for null (or track a bool flag) before calling WithKeyVault","Split configuration so each project resource gets exactly one Key Vault connection"],"exampleFix":"// before\nvar project = foundry.AddProject(\"proj\").WithKeyVault(kvA).WithKeyVault(kvB);\n\n// after\nvar project = foundry.AddProject(\"proj\").WithKeyVault(kvA);","handlingStrategy":"validation","validationCode":"if (project.Resource.KeyVaultConn is null)\n{\n    project.WithKeyVault(keyVault);\n}","typeGuard":null,"tryCatchPattern":"try { project.WithKeyVault(keyVault); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already has a Key Vault connection\"))\n{\n    // Key Vault already attached; skip.\n}","preventionTips":["Call WithKeyVault exactly once per project resource, ideally at its creation site","Centralize project configuration in one method to avoid duplicate calls","Guard with a null check on KeyVaultConn before calling"],"tags":["csharp","aspire","azure","duplicate-configuration"],"backgroundTag":"invalid-state-transition","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"}