microsoft/aspire · error · InvalidOperationException

Existing connector connection

Error message

Existing connector connection '{builder.Resource.Name}' is read-only and cannot create an access policy.

What it means

WithAccessPolicy on an Azure Connector Namespace connection refuses to add an access policy when the underlying resource was declared as existing (AsExisting). Existing references are read-only pointers to infrastructure Aspire does not own, so it cannot create or mutate access policies on them. The library throws early at model-build time rather than failing during deployment.

Solutions

  1. Remove the WithAccessPolicy call and manage the access policy on the existing connection directly in Azure (portal/CLI/Bicep).
  2. If you truly need code-managed access policies, create the connector connection in the app model instead of marking it AsExisting.
  3. Guard the call: only invoke WithAccessPolicy when builder.Resource.IsExisting is false, or skip it conditionally for existing resources.

Example fix

// before
var connection = azure.AddConnectorConnection("existing-conn").AsExisting();
connection.WithAccessPolicy("app-policy", policyOptions); // throws

// after
var connection = azure.AddConnectorConnection("existing-conn").AsExisting();
// Manage the access policy for the existing connection outside Aspire;
// reference it without WithAccessPolicy.
Defensive patterns

Strategy: validation

Validate before calling

if (builder.Resource.IsExisting)
{
    // manage the access policy out-of-band instead of calling WithAccessPolicy
}
else
{
    connection.WithAccessPolicy("app-policy", policyOptions);
}

Try / catch

try
{
    connection.WithAccessPolicy("app-policy", policyOptions);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("is read-only"))
{
    // fall back to out-of-band policy management for existing connections
}

Prevention

When it happens

Trigger: Calling WithAccessPolicy(...) on an IResourceBuilder for a connector connection whose resource has IsExisting == true, i.e. after calling .AsExisting() (or constructing the resource as an existing reference).

Common situations: Pointing an app at a pre-provisioned connector connection with AsExisting and then trying to attach an access policy for a compute resource; copying fluent-modeling code that was written for newly-created connections onto an existing-reference builder.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

    [AspireExport]
    public static IResourceBuilder<AzureConnectorNamespaceConnectionResource> WithAccessPolicy(
        this IResourceBuilder<AzureConnectorNamespaceConnectionResource> builder,
        [ResourceName] string name,
        AzureConnectorNamespaceAccessPolicyOptions options)
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentException.ThrowIfNullOrWhiteSpace(name);
        ArgumentNullException.ThrowIfNull(options);
        ValidateEntraPrincipalIds(
            options.ObjectId,
            options.TenantId,
            "connection access policy",
            nameof(options.ObjectId),
            nameof(options.TenantId),
            nameof(options));
        if (builder.Resource.IsExisting)
        {
            throw new InvalidOperationException(
                $"Existing connector connection '{builder.Resource.Name}' is read-only and cannot create an access policy.");
        }

        var policyName = options.PolicyName ?? name;
        ValidateConnectorResourceName(policyName, nameof(options));
        var resourceName = GetValidatedAccessPolicyResourceName(builder.Resource, name, policyName);

        builder.Resource.AccessPolicies.Add(new AzureConnectorNamespaceConnectionAccessPolicyResource(
            resourceName,
            policyName,
            builder.Resource,
            options.ObjectId,
            options.TenantId));
        return builder;
    }

    /// <summary>
    /// Adds a connection access policy for a user-assigned managed identity.

View on GitHub (pinned to 25830f84bd)