microsoft/aspire · error

ContainerServiceManagedCluster.Properties returned null.

Error message

ContainerServiceManagedCluster.Properties returned null.

What it means

After locating ContainerServiceManagedCluster.Properties via reflection, the injector reads its value; if the reflection GetValue returns null this error is thrown. The injector expects the cluster construct to always carry a non-null internal ManagedClusterProperties instance, so a null indicates the provisioning model's initialization behavior changed.

Solutions

  1. Pin Azure.Provisioning.ContainerService to 1.0.0-beta.6 (the version this injector was written for) in Directory.Packages.props
  2. If upgrading deliberately, touch any typed property first (e.g. set a cluster property) before calling the injector so the lazy object initializes, or update the injector to construct the properties object itself
  3. Verify no transitive dependency downgrades/overrides the Azure.Provisioning core assembly — check the resolved versions with dotnet list package --include-transitive
  4. Track microsoft/aspire#17060 and Azure/azure-sdk-for-net#59225 for the typed upstream API that removes the reflection workaround

Example fix

// before
var clusterProps = clusterPropsProp.GetValue(aks)
    ?? throw new InvalidOperationException("ContainerServiceManagedCluster.Properties returned null.");
// after (tolerate lazily-initialized models)
var clusterProps = clusterPropsProp.GetValue(aks);
if (clusterProps is null)
{
    clusterProps = Activator.CreateInstance(clusterPropsProp.PropertyType, aks);
    clusterPropsProp.SetValue(aks, clusterProps);
}
Defensive patterns

Strategy: try-catch

Validate before calling

var propsProp = typeof(ContainerServiceManagedCluster).GetProperty("Properties", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var propsValue = propsProp?.GetValue(aks);
if (propsValue is null)
{
    throw new InvalidOperationException("Cluster Properties object is null; ensure a typed cluster property was set before injecting preview ingress settings.");
}

Try / catch

try
{
    AksPreviewIngressProfileInjector.Inject(aks, gatewayApi, applicationLoadBalancer);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Properties returned null"))
{
    // Lazy-init semantics changed: nudge initialization by setting a typed property first.
    aks.DnsPrefix ??= BicepValue<string>.Create("aspire");
    AksPreviewIngressProfileInjector.Inject(aks, gatewayApi, applicationLoadBalancer);
}

Prevention

When it happens

Trigger: AksPreviewIngressProfileInjector.Inject runs (gatewayApi or applicationLoadBalancer enabled on an AKS cluster), the Properties property exists via reflection, but the installed Azure.Provisioning.ContainerService version returns null from the Properties getter — e.g. a version where the complex object is only created on first typed-property access rather than in the constructor.

Common situations: Package upgrade to a different Azure.Provisioning.ContainerService beta with changed lazy-init semantics; building the cluster via a different construction path that skips Properties initialization; mixing mismatched Azure.Provisioning core and ContainerService assemblies.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Azure.Kubernetes/AksPreviewIngressProfileInjector.cs:167

                    /* isRequired */ false,
                    /* isSecure */ false,
                    /* defaultValue */ null,
                    /* format */ null,
                ])!;
            enabled.Assign(true);
        }
    }

    private static object GetIngressProfileInstance(ContainerServiceManagedCluster aks)
    {
        // ContainerServiceManagedCluster.Properties is internal and exposes the
        // ManagedClusterProperties complex object that owns IngressProfile (also internal).
        var clusterPropsProp = typeof(ContainerServiceManagedCluster).GetProperty(
            "Properties",
            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
            ?? throw new InvalidOperationException("ContainerServiceManagedCluster.Properties not found via reflection. The Azure.Provisioning surface may have changed; review AksPreviewIngressProfileInjector.");
        var clusterProps = clusterPropsProp.GetValue(aks)
            ?? throw new InvalidOperationException("ContainerServiceManagedCluster.Properties returned null.");

        var ipProp = clusterProps.GetType().GetProperty(
            "IngressProfile",
            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
            ?? throw new InvalidOperationException("ManagedClusterProperties.IngressProfile not found via reflection. The Azure.Provisioning surface may have changed; review AksPreviewIngressProfileInjector.");
        var ipInstance = ipProp.GetValue(clusterProps)
            ?? throw new InvalidOperationException("ManagedClusterProperties.IngressProfile was null even after assigning IngressWebAppRouting; the Azure.Provisioning lazy-initialization behavior may have changed.");

        if (ipInstance.GetType().FullName != IngressProfileTypeFullName)
        {
            throw new InvalidOperationException($"Expected IngressProfile to be a {IngressProfileTypeFullName} but found {ipInstance.GetType().FullName}.");
        }

        return ipInstance;
    }
}

View on GitHub (pinned to 25830f84bd)