microsoft/aspire · error · RadiusBackingResourceProjectionException

ASPIRERADIUS082

ASPIRERADIUS082

Error message

Resource '{resource.Name}' would be deployed with the user name 'guest', which RabbitMQ restricts to loopback connections — the deployed broker would reject every workload that connects to it. Supply an explicit user name, for example AddRabbitMQ("{resource.Name}", userName: builder.AddParameter("{resource.Name}user")), so the same value is both provisioned on the broker and composed into the connection string. Diagnostic: ASPIRERADIUS082.

What it means

RadiusInfrastructureBuilder emits the RabbitMQ construct's Bicep and guards against the 'guest' user name at build time: if the emitted username property renders as the literal 'guest', or the backing user-name parameter resolves to 'guest', it throws CreateRabbitMqGuestUserNameException (ASPIRERADIUS082). This is the infrastructure-generation counterpart of the deploy-time check, deliberately comparing the resolved parameter rather than just the Bicep literal so the guard cannot be bypassed with a parameter indirection.

Solutions

  1. Supply an explicit non-'guest' userName parameter: AddRabbitMQ("name", userName: builder.AddParameter("nameuser"))
  2. Update the parameter source (parameter default, environment variable, secret reference) so it no longer resolves to 'guest'
  3. Redeploy/publish after changing the credential so the generated Bicep and connection string both carry the new user name
  4. Keep the same parameter wired to both the broker resource and consuming connection strings to avoid credential drift

Example fix

// before: username emitted as 'guest'
var rabbit = builder.AddRabbitMQ("bus");

// after: explicit parameterized user name
var busUser = builder.AddParameter("bususer");
var busPass = builder.AddParameter("buspass", secret: true);
var rabbit = builder.AddRabbitMQ("bus", userName: busUser, password: busPass);
Defensive patterns

Strategy: validation

Validate before calling

// Check the resolved user-name parameter before publish
var resolved = await userNameParameter.GetValueAsync(ct);
if (resolved is null || resolved == "guest")
    throw new InvalidOperationException("RabbitMQ userName parameter resolves to 'guest'; supply a real user name.");

Type guard

bool NotGuest(string? v) => !string.IsNullOrWhiteSpace(v) && v != "guest";

Try / catch

try
{
    await builder.CreateInfrastructureAsync(model, ct);
}
catch (Exception ex) when (ex.Message.Contains("ASPIRERADIUS082"))
{
    // Provisioning-time guard: fix the AddRabbitMQ userName parameter and regenerate.
    throw;
}

Prevention

When it happens

Trigger: Publishing/transforming an Aspire model where AddRabbitMQ's emitted username schema property renders to 'guest', or its userName parameter's GetValueAsync resolves to "guest" during Bicep generation for a Radius environment.

Common situations: RabbitMQ resource declared without an explicit userName so defaults to guest; a parameter default of 'guest'; environment config supplying 'guest'; local development using RabbitMQ's default guest account being published unchanged to Radius.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs:2823

        // Neither alternative can be made correct silently:
        //   - emitting `guest` provisions a broker no workload can authenticate against;
        //   - emitting `radius` instead leaves the connection string Aspire already composed saying
        //     `guest`, because a default user name arrives as literal text inside the format string
        //     with no value provider to substitute (the same gap DefaultUserName_RemainsALiteral
        //     pins), so the two would disagree.
        // So this fails the publish instead, and names the one-line fix.
        //
        // Both spellings of `guest` have to be caught. A literal user name renders as the Bicep
        // string literal `'guest'`, but a parameter-supplied one renders as a Bicep *identifier*
        // (`param queueuser`), so the rendered text says nothing about the value. Supplying a
        // parameter is exactly the remediation the message below recommends, so missing that case
        // would route users around the guard with the guard's own advice. Parameter values are
        // normally known at publish time, so resolve it and compare.
        if (construct.GetSchemaProperty("username") is { } emittedUserName &&
            (RenderBicepValue(emittedUserName) is "'guest'" ||
             await ResolvesToGuestUserNameAsync(userNameParameter).ConfigureAwait(false)))
        {
            throw CreateRabbitMqGuestUserNameException(resource);
        }

        // `queue` is deliberately not emitted. It is optional on the type, and Aspire's model has no
        // queue concept to map from — AddRabbitMQ declares a broker, not a queue — so any value here
        // would be invented. The UDT's own default (`jobs`) applies instead, and consumers create
        // the queues they need through the AMQP client.
    }

    /// <summary>
    /// Determines whether a parameter-supplied user name resolves to RabbitMQ's <c>guest</c>
    /// account, which the emitted Bicep cannot reveal because a parameter renders as an identifier
    /// rather than as its value.
    /// </summary>
    /// <remarks>
    /// A parameter whose value cannot be produced while publishing (no value configured, or a
    /// default only the deployment can materialize) is treated as not being <c>guest</c>: the guard
    /// exists to catch the value Aspire itself composed into the connection string, and failing the
    /// publish on an unknowable value would reject models that are perfectly valid.

View on GitHub (pinned to 25830f84bd)