microsoft/aspire · error

aspire: returned unexpected type %T

Error message

aspire: {capability.CapabilityId} returned unexpected type %T

What it means

Generated Go capability methods invoke the capability over the socket and then assert the returned value has the expected Go type. If the remote side returns something of a different concrete type, the type assertion fails and this error is stored on the errored builder. It signals a protocol/shape mismatch between the AppHost and the generated client.

Solutions

  1. Regenerate the Go client from the current AppHost so return types match the live capability contract
  2. Upgrade the AppHost/CLI and Go client to matching versions
  3. Inspect the server-side capability implementation to confirm it returns the declared type
Defensive patterns

Strategy: try-catch

Try / catch

result, err := client.SomeCapability(ctx, arg)
if err != nil {
	// covers type-mismatch errors stored by setErr
	return fmt.Errorf("capability call failed: %w", err)
}

Prevention

When it happens

Trigger: A capability invoked via a generated method (with a declared return type) returns a value whose Go concrete type does not match the generated returnGoType assertion.

Common situations: Mismatched versions of the AppHost and the generated Go client (contract drift), a server-side bug returning nil or a different handle type, or custom/patched capability implementations.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.CodeGeneration.Go/AtsGoCodeGenerator.cs:1310

            ? implTarget
            : null;

        if (childImplName is null)
        {
            // No registered impl for this typeId (e.g. *ReferenceExpression,
            // which is hand-written in base.go). Cast the wrapIfHandle result
            // directly to the declared return type. Errors land on s; we
            // return nil and the caller must consult s.Err().
            var returnGoType = MapTypeRefToGo(returnType, false);
            WriteLine("\tif s.err != nil { return nil }");
            EmitHandleParamErrorChecks("\t", capability, "s.setErr(err); return nil");
            EmitUnionTypeChecks("\t", capability, methodName, new[] { "s.setErr(err); return nil" });
            EmitArgsConstruction("\t", capability, requiredParams, optionalParams, targetParamName, "s.handle");
                WriteLine($"\tresult, err := s.client.invokeCapability(ctx, \"{capability.CapabilityId}\", reqArgs)");
            WriteLine("\tif err != nil { s.setErr(err); return nil }");
            WriteLine($"\ttyped, ok := result.({returnGoType})");
            WriteLine("\tif !ok {");
            WriteLine($"\t\ts.setErr(fmt.Errorf(\"aspire: {capability.CapabilityId} returned unexpected type %T\", result))");
            WriteLine("\t\treturn nil");
            WriteLine("\t}");
            WriteLine("\treturn typed");
            return;
        }

        // Pre-errored child path: parent failure short-circuits this call.
        WriteLine($"\tif s.err != nil {{ return &{childImplName}{{resourceBuilderBase: newErroredResourceBuilder(s.err, s.client)}} }}");
        EmitHandleParamErrorChecks("\t", capability,
            $"return &{childImplName}{{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}}");
        EmitUnionTypeChecks("\t", capability, methodName, new[]
        {
            $"return &{childImplName}{{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}}",
        });
        EmitArgsConstruction("\t", capability, requiredParams, optionalParams, targetParamName, "s.handle");
        WriteLine($"\tresult, err := s.client.invokeCapability(ctx, \"{capability.CapabilityId}\", reqArgs)");
        WriteLine("\tif err != nil {");
        WriteLine($"\t\treturn &{childImplName}{{resourceBuilderBase: newErroredResourceBuilder(err, s.client)}}");

View on GitHub (pinned to 25830f84bd)