microsoft/aspire · error · InvalidOperationException

' ' is missing Build().

Error message

'{builder.GetType().FullName}' is missing Build().

What it means

BuildReferenceExpression reflectively locates the public parameterless Build() method on the ReferenceExpression.Builder and invokes it to produce the final expression. If no such method exists, this InvalidOperationException is thrown naming the builder's type.

Solutions

  1. Verify the builder is ReferenceExpression.Builder from a compatible Aspire.Hosting version.
  2. Align package versions across Aspire.Hosting / RemoteHost projects.
  3. Add trimming preservation for ReferenceExpression.Builder.Build if publishing AOT/trimmed.
  4. Confirm AppendLiteral/AppendValueProvider steps succeeded earlier — a wrong-type builder earlier in the flow surfaces here.

Example fix

// before
<PackageReference Include="Aspire.Hosting" Version="9.*" />

// after
<PackageReference Include="Aspire.Hosting" Version="13.*" /> <!-- matches RemoteHost expectations -->
Defensive patterns

Strategy: type-guard

Validate before calling

var m = builder.GetType().GetMethod("Build", BindingFlags.Instance | BindingFlags.Public);
if (m is null)
    throw new NotSupportedException($"{builder.GetType().FullName} lacks a public Build(); it is not a ReferenceExpression.Builder.");

Type guard

static bool SupportsBuild(object builder) =>
    builder.GetType().GetMethod("Build", BindingFlags.Instance | BindingFlags.Public) is not null;

Try / catch

try
{
    var expr = BuildReferenceExpression(builder);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("missing Build()"))
{
    logger.LogError(ex, "Cannot finalize reference expression: {Message}", ex.Message);
}

Prevention

When it happens

Trigger: ToValueReferenceExpression finishes appending literal/value parts and calls BuildReferenceExpression(builder); GetMethod("Build", Public|Instance) returns null because the object is not the expected builder or the API changed.

Common situations: Version mismatch between the RemoteHost code and the loaded Aspire.Hosting assembly; passing a wrong object; trimming removing Build() in AOT builds.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.RemoteHost/Ats/ReferenceExpressionRef.cs:355

    }

    private static void AppendValueProvider(object builder, object valueProvider)
    {
        var appendValueProviderMethod = builder.GetType().GetMethod(
            "AppendValueProvider",
            BindingFlags.Instance | BindingFlags.Public,
            binder: null,
            [typeof(object), typeof(string)],
            modifiers: null)
            ?? throw new InvalidOperationException($"'{builder.GetType().FullName}' is missing AppendValueProvider(object, string).");

        appendValueProviderMethod.Invoke(builder, [valueProvider, null]);
    }

    private static object BuildReferenceExpression(object builder)
    {
        var buildMethod = builder.GetType().GetMethod("Build", BindingFlags.Instance | BindingFlags.Public)
            ?? throw new InvalidOperationException($"'{builder.GetType().FullName}' is missing Build().");

        return buildMethod.Invoke(builder, null)
            ?? throw new InvalidOperationException($"'{builder.GetType().FullName}.Build()' returned null.");
    }

    private static object CreateConditionalReferenceExpression(
        object condition,
        string matchValue,
        object whenTrue,
        object whenFalse)
    {
        var referenceExpressionType = GetRequiredHostingType(HostingTypeNames.ReferenceExpression, condition);
        var valueProviderType = GetRequiredHostingType(HostingTypeNames.ValueProviderInterface, condition);

        var createConditionalMethod = referenceExpressionType.GetMethod(
            "CreateConditional",
            BindingFlags.Public | BindingFlags.Static,
            binder: null,

View on GitHub (pinned to 25830f84bd)