microsoft/aspire · error · InvalidOperationException

An access policy for principal

Error message

An access policy for principal '{objectId}' is already registered on MCP server configuration '{config.Name}'.

What it means

Each Entra principal (object ID) may have at most one access policy per MCP server configuration. GetValidatedMcpAccessPolicyResourceName throws this InvalidOperationException when a policy for the same object ID (case-insensitive) already exists on the configuration.

Solutions

  1. Remove the duplicate WithAccessPolicy call for that object ID.
  2. Reuse the existing policy instead of adding a new one.
  3. Deduplicate principals before configuring, e.g. DistinctBy(p => p.ObjectId, StringComparer.OrdinalIgnoreCase).

Example fix

// before
config.WithAccessPolicy("policyA", objectId, tenantId, PrincipalType.User);
config.WithAccessPolicy("policyB", objectId, tenantId, PrincipalType.User); // same objectId
// after
config.WithAccessPolicy("policyA", objectId, tenantId, PrincipalType.User);
Defensive patterns

Strategy: validation

Validate before calling

if (config.AccessPolicies.Any(p => string.Equals(p.ObjectId, objectId, StringComparison.OrdinalIgnoreCase)))
{
    // principal already has a policy; skip
}

Try / catch

try { config.WithAccessPolicy(name, objectId, tenantId, principalType); }
catch (InvalidOperationException ex) when (ex.Message.Contains("principal"))
{
    // skip duplicate principal or reuse existing policy
}

Prevention

When it happens

Trigger: Calling WithAccessPolicy twice on the same MCP server configuration passing the same Entra object ID, even with different resource/policy names.

Common situations: Granting the same service principal or managed identity access twice under different names; loops over principals that contain duplicates; re-running configuration code on the same builder.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/62736dbd9130d40c. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Azure.ConnectorNamespace/AzureConnectorNamespaceExtensions.cs:704

        AzureConnectorNamespaceMcpServerConfigResource config,
        string name,
        string objectId)
    {
        var resourceName = ConnectorNamespaceBicepIdentifiers.CreateMcpAccessPolicy(
            config.Parent.Name,
            config.Name,
            name);
        if (config.AccessPolicies.Any(policy =>
            string.Equals(policy.BicepIdentifier, resourceName, StringComparison.OrdinalIgnoreCase)))
        {
            throw new InvalidOperationException(
                $"Access policy resource '{name}' is already registered on MCP server configuration '{config.Name}'.");
        }

        if (config.AccessPolicies.Any(policy =>
            string.Equals(policy.ObjectId, objectId, StringComparison.OrdinalIgnoreCase)))
        {
            throw new InvalidOperationException(
                $"An access policy for principal '{objectId}' is already registered on MCP server configuration '{config.Name}'.");
        }

        return resourceName;
    }

    private static void ValidateMcpAccessPolicyOptions(AzureConnectorNamespaceMcpAccessPolicyOptions options)
    {
        ValidateEntraPrincipalIds(
            options.ObjectId,
            options.TenantId,
            "MCP access policy",
            nameof(options.ObjectId),
            nameof(options.TenantId),
            nameof(options));

        if (!Enum.IsDefined(options.PrincipalType))
        {

View on GitHub (pinned to 25830f84bd)