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

  1. 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
  2. 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)
  3. Clear stale package caches and restore to ensure the expected assembly version is actually bound (bind redirects / transitive downgrades)
  4. 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

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


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)