microsoft/aspire · error
ProvisionableConstruct.DefineProperty
Error message
ProvisionableConstruct.DefineProperty<T> not found via reflection. The Azure.Provisioning surface may have changed; review AksPreviewIngressProfileInjector.
What it means
AksPreviewIngressProfileInjector locates the protected generic ProvisionableConstruct.DefineProperty<T> method via reflection to emit preview-only AKS ingressProfile Bicep properties. This error is thrown from the static Lazy initializer when GetMethod("DefineProperty", NonPublic|Instance) returns null, meaning the Azure.Provisioning assembly no longer contains a method with that exact name/signature binding — a package-version drift guard.
Solutions
- Pin Azure.Provisioning.ContainerService to a version known to work (1.0.0-beta.6 or the version Aspire was built against) via Directory.Packages.props
- Check the new Azure.Provisioning source for DefineProperty's current name/signature and update the reflection lookup in AksPreviewIngressProfileInjector (or the public-subclass replacement if ManagedClusterIngressProfile is now public)
- Clear stale package caches and restore to ensure the expected assembly version is actually bound (bind redirects / transitive downgrades)
- Track microsoft/aspire#17060 and Azure/azure-sdk-for-net#59225 — when the typed API ships upstream, remove the reflection path
Example fix
// before
return typeof(ProvisionableConstruct).GetMethod("DefineProperty", BindingFlags.NonPublic | BindingFlags.Instance)
?? throw new InvalidOperationException("...DefineProperty<T> not found...");
// after (if upstream renamed/overloaded it)
return typeof(ProvisionableConstruct).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
.Single(m => m.Name == "DefineProperty" && m.IsGenericMethodDefinition)
?? throw new InvalidOperationException("...DefineProperty<T> not found..."); Defensive patterns
Strategy: fallback
Validate before calling
var defineProperty = typeof(ProvisionableConstruct).GetMethod("DefineProperty",
BindingFlags.NonPublic | BindingFlags.Instance);
if (defineProperty is null)
{
// Pre-flight check before enabling preview ingress features.
throw new InvalidOperationException("Installed Azure.Provisioning version is incompatible with AKS preview ingress injection; pin Azure.Provisioning.ContainerService 1.0.0-beta.6.");
} Try / catch
try
{
AksPreviewIngressProfileInjector.Inject(aks, gatewayApi: true, applicationLoadBalancer: false);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("DefineProperty"))
{
// Package drift: surface the resolved Azure.Provisioning version in the message.
throw new InvalidOperationException($"Azure.Provisioning version mismatch (DefineProperty missing). Verify the pinned package version.", ex);
} Prevention
- Pin Azure.Provisioning.* versions in Directory.Packages.props instead of floating
- Check azure-sdk-for-net release notes for ProvisionableConstruct API changes before upgrading
- Run a publish/Bicep-generation test whenever the provisioning package version changes
- Add a unit test that touches s_defineProperty.Value early so drift fails in tests, not at user publish time
- Track aspire#17060 / Azure#59225 and migrate to the typed API when available
When it happens
Trigger: Upgrading Azure.Provisioning (Azure.Provisioning.ContainerService) to a version that renamed, removed, or changed the binding flags/overload resolution of DefineProperty<T> on ProvisionableConstruct, then building/publishing an app model that enables Gateway API or Application Load Balancer on an AKS cluster (Inject is called, and s_defineProperty.Value is first evaluated).
Common situations: Central package management bumps Azure.Provisioning.* to a newer beta; a transitive dependency pulls a different Azure.Provisioning major; MAUI/SDK unification changes binding behavior; upgrading Aspire against a newer azure-sdk-for-net beta where the reflection contract broke.
Related errors
- ContainerServiceManagedCluster.Properties not found via…
- ManagedClusterProperties.IngressProfile not found via…
- ContainerServiceManagedCluster.Properties returned null.
- 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/77ab4d691a2edae7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Kubernetes/AksPreviewIngressProfileInjector.cs:95
/// <para>
/// Tracked by <see href="https://github.com/microsoft/aspire/issues/17060"/> (Aspire) and
/// <see href="https://github.com/Azure/azure-sdk-for-net/issues/59225"/> (upstream).
/// </para>
/// </remarks>
// TODO: https://github.com/microsoft/aspire/issues/17060 - delete this class once
// Azure.Provisioning.ContainerService exposes ManagedClusterIngressProfile publicly
// with typed GatewayApi and ApplicationLoadBalancer properties.
internal static class AksPreviewIngressProfileInjector
{
private const string IngressProfileTypeFullName = "Azure.Provisioning.ContainerService.ManagedClusterIngressProfile";
private static readonly Lazy<MethodInfo> s_defineProperty = new(() =>
{
// protected BicepValue<T> DefineProperty<T>(string propertyName, string[] bicepPath, bool isOutput = false, bool isRequired = false, bool isSecure = false, BicepValue<T>? defaultValue = null, string? format = null)
return typeof(ProvisionableConstruct).GetMethod(
"DefineProperty",
BindingFlags.NonPublic | BindingFlags.Instance)
?? throw new InvalidOperationException("ProvisionableConstruct.DefineProperty<T> not found via reflection. The Azure.Provisioning surface may have changed; review AksPreviewIngressProfileInjector.");
});
/// <summary>
/// Injects the requested preview-only ingressProfile entries onto <paramref name="aks"/>.
/// Caller is responsible for setting an appropriate preview <c>ResourceVersion</c> on
/// the cluster (e.g. <c>2025-09-02-preview</c>) before any properties are compiled.
/// </summary>
public static void Inject(ContainerServiceManagedCluster aks, bool gatewayApi, bool applicationLoadBalancer)
{
if (!gatewayApi && !applicationLoadBalancer)
{
return;
}
// Bootstrap the lazily-created internal IngressProfile by assigning an empty
// WebAppRouting object via the public setter. An empty WebAppRouting object is
// filtered out at emission time, so this does not introduce a stray webAppRouting
// entry into the rendered Bicep.View on GitHub (pinned to 25830f84bd)