microsoft/aspire · error · InvalidOperationException
ASPIRERADIUS084
ASPIRERADIUS084
Error message
Environment variable '{reference.Key}' on container '{reference.ResourceName}' holds a credential and reads it from the '{RadiusResourceTypes.SecuritySecrets}' resource '{reference.Secret.BicepIdentifier}', but a ConfigureRadiusInfrastructure callback removed that resource. Keep the resource, or set '{reference.Key}' explicitly in the callback. Diagnostic: ASPIRERADIUS084. What it means
Container environment variables marked as holding credentials are wired to reference a generated Security/secrets resource. If a ConfigureRadiusInfrastructure callback removed that secret resource, the environment variable would have nothing to resolve, producing an invalid deployment, so the builder throws early with ASPIRERADIUS084.
Solutions
- Keep the referenced secret resource in the model.
- Set the environment variable '{reference.Key}' explicitly (to a literal or your own secret) in the callback instead of removing its source.
- If replacing with a custom secret, update the container's environment variable reference to the new secret.
Example fix
// before
callback: b =>
{
b.RemoveResource("connection-secret"); // container env var still points at it
}
// after
callback: b =>
{
// keep the resource, or explicitly set the env var:
// b.SetEnvironmentVariable("frontend", "Connection__Password", mySecretRef);
} Defensive patterns
Strategy: validation
Validate before calling
// In a callback, only remove resources nothing depends on
var referencedSecrets = model.Resources
.SelectMany(r => r.Annotations.OfType<EnvironmentReferenceAnnotation>())
.Select(a => a.SecretName)
.ToHashSet();
if (referencedSecrets.Contains(candidate.Name))
throw new InvalidOperationException($"'{candidate.Name}' backs container credential env vars and cannot be removed."); Try / catch
try { await builder.ExecuteCallbacksAsync(ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("ASPIRERADIUS084"))
{
logger.LogError(ex, "Callback removed a secret backing a container credential env var; keep it or set the env var explicitly.");
} Prevention
- Keep generated secret resources referenced by container environment variables
- Set credential env vars explicitly in the callback if you must remove their source secret
- Audit callbacks that delete resources wholesale; scope removals to resources with no inbound references
When it happens
Trigger: Running ConfigureRadiusInfrastructure callbacks that remove a SecuritySecrets resource still referenced by a container's credential environment variable ('{reference.Key}' on '{reference.ResourceName}').
Common situations: Callbacks that strip all generated secret resources; cleanup loops deleting resources by type without checking references; consolidating secrets into a custom one without repointing the container's env var.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- A ConfigureRadiusInfrastructure callback changed the value…
- ASPIRERADIUS074
- Radius resource ' ' reads its ' ' from key ' ' of the ' '…
- ASPIRERADIUS042
- ASPIRERADIUS044
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/429f262cc746d1a7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs:1074
// the variable's construct owns the result — last-write-wins, as everywhere else.
if (reference.Container is null ||
!liveContainers.Contains(reference.Container) ||
!reference.Container.Env.TryGetValue(reference.Key, out var currentEnvVar) ||
// BicepDictionary wraps each entry, so unwrap before comparing construct identity.
!ReferenceEquals(currentEnvVar?.Value, reference.EnvVar))
{
continue;
}
// The callback re-pointed the reference itself.
if (!string.Equals(RenderBicepValue(reference.EnvVar.SecretName), reference.OriginalSecretName, StringComparison.Ordinal))
{
continue;
}
if (!liveSecrets.Contains(reference.Secret))
{
throw new InvalidOperationException(
$"Environment variable '{reference.Key}' on container '{reference.ResourceName}' holds a credential " +
$"and reads it from the '{RadiusResourceTypes.SecuritySecrets}' resource " +
$"'{reference.Secret.BicepIdentifier}', but a ConfigureRadiusInfrastructure callback removed that " +
$"resource. Keep the resource, or set '{reference.Key}' explicitly in the callback. " +
$"Diagnostic: ASPIRERADIUS084.");
}
// Validate the key the variable *currently* carries rather than the one the publisher
// wrote. A callback can re-point the key alone — leaving SecretName aimed at this
// generated secret and so passing the guard above — and checking the original key would
// find it present and publish a `secretKeyRef` naming a key that does not exist. Radius
// accepts that artifact and the failure surfaces as a pod that never starts.
//
// Two shapes are deliberately left alone: a key rendered as a Bicep expression only
// resolves at deploy time, so there is nothing to compare it against, and a cleared key
// is already rejected by the SecretName/SecretKey pairing check (ASPIRERADIUS087).
if (IsBicepExpression(reference.EnvVar.SecretKey) ||
RenderBicepLiteral(reference.EnvVar.SecretKey) is not { } currentSecretKey)View on GitHub (pinned to 25830f84bd)