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
- Pin Azure.Provisioning.ContainerService to 1.0.0-beta.6 (the version this injector was written for) in Directory.Packages.props
- 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
- Verify no transitive dependency downgrades/overrides the Azure.Provisioning core assembly — check the resolved versions with dotnet list package --include-transitive
- 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
- Set at least one typed cluster property (DnsPrefix, AgentPoolProfiles, etc.) before injecting preview ingress settings
- Avoid mixing Azure.Provisioning core and ContainerService packages from different release trains
- Confirm resolved package versions with dotnet list package --include-transitive after any bump
- Prefer setting the empty IngressWebAppRouting (as Inject does) before reading nested properties
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
- ContainerServiceManagedCluster.Properties not found via…
- ManagedClusterProperties.IngressProfile not found via…
- ProvisionableConstruct.DefineProperty
- Expected IngressProfile to be a…
- ManagedClusterProperties.IngressProfile was null even after…
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)