microsoft/aspire · error · InvalidOperationException

' .Build()' returned null.

Error message

'{builder.GetType().FullName}.Build()' returned null.

What it means

After reflectively invoking Builder.Build(), BuildReferenceExpression expects a non-null ReferenceExpression and throws this InvalidOperationException if the invocation returns null. This is a defensive invariant: Build() should always produce an expression for a well-formed builder.

Solutions

  1. Ensure the builder has at least one AppendLiteral/AppendValueProvider part before calling Build (some versions return null for empty builders).
  2. Align Aspire.Hosting package versions to a release where Build() is non-nullable ReferenceExpression.
  3. Inspect the loaded Aspire.Hosting.dll version at runtime to rule out assembly conflicts.
  4. If you cannot guarantee non-empty content, append an empty-string literal before Build().

Example fix

// before
var builder = CreateReferenceExpressionBuilder();
var expr = BuildReferenceExpression(builder); // no parts added

// after
var builder = CreateReferenceExpressionBuilder();
AppendLiteral(builder, string.Empty); // guarantees Build() has content
var expr = BuildReferenceExpression(builder);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the builder has content before invoking Build().
var buildMethod = builder.GetType().GetMethod("Build", BindingFlags.Instance | BindingFlags.Public)
    ?? throw new NotSupportedException("No Build() method; wrong builder type.");

Try / catch

try
{
    var expr = BuildReferenceExpression(builder);
}
catch (InvalidOperationException ex) when (ex.Message.EndsWith("Build()' returned null."))
{
    AppendLiteral(builder, string.Empty);
    var expr = BuildReferenceExpression(builder); // retry with guaranteed content
}

Prevention

When it happens

Trigger: Build() invoked successfully but returned null — only realistically when the resolved Build() is an unexpected override/return shape from a mismatched assembly, or the wrong builder object was used.

Common situations: Custom/patched Aspire.Hosting build whose Build() returns null on empty builders; version mismatch causing the wrong Build overload to be selected.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

    {
        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,
            [valueProviderType, typeof(string), referenceExpressionType, referenceExpressionType],
            modifiers: null)
            ?? throw new InvalidOperationException($"'{referenceExpressionType.FullName}' is missing CreateConditional(...).");

View on GitHub (pinned to 25830f84bd)