{"record":{"id":"429f262cc746d1a7","repo":"microsoft/aspire","slug":"aspireradius084","errorCode":"ASPIRERADIUS084","errorMessage":"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.","messagePattern":"Environment variable '(.+?)' on container '(.+?)' holds a credential and reads it from the '(.+?)' resource '(.+?)', but a ConfigureRadiusInfrastructure callback removed that resource\\. Keep the resource, or set '(.+?)' explicitly in the callback\\. Diagnostic: ASPIRERADIUS084\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs","lineNumber":1074,"sourceCode":"            // the variable's construct owns the result — last-write-wins, as everywhere else.\n            if (reference.Container is null ||\n                !liveContainers.Contains(reference.Container) ||\n                !reference.Container.Env.TryGetValue(reference.Key, out var currentEnvVar) ||\n                // BicepDictionary wraps each entry, so unwrap before comparing construct identity.\n                !ReferenceEquals(currentEnvVar?.Value, reference.EnvVar))\n            {\n                continue;\n            }\n\n            // The callback re-pointed the reference itself.\n            if (!string.Equals(RenderBicepValue(reference.EnvVar.SecretName), reference.OriginalSecretName, StringComparison.Ordinal))\n            {\n                continue;\n            }\n\n            if (!liveSecrets.Contains(reference.Secret))\n            {\n                throw new InvalidOperationException(\n                    $\"Environment variable '{reference.Key}' on container '{reference.ResourceName}' holds a credential \" +\n                    $\"and reads it from the '{RadiusResourceTypes.SecuritySecrets}' resource \" +\n                    $\"'{reference.Secret.BicepIdentifier}', but a ConfigureRadiusInfrastructure callback removed that \" +\n                    $\"resource. Keep the resource, or set '{reference.Key}' explicitly in the callback. \" +\n                    $\"Diagnostic: ASPIRERADIUS084.\");\n            }\n\n            // Validate the key the variable *currently* carries rather than the one the publisher\n            // wrote. A callback can re-point the key alone — leaving SecretName aimed at this\n            // generated secret and so passing the guard above — and checking the original key would\n            // find it present and publish a `secretKeyRef` naming a key that does not exist. Radius\n            // accepts that artifact and the failure surfaces as a pod that never starts.\n            //\n            // Two shapes are deliberately left alone: a key rendered as a Bicep expression only\n            // resolves at deploy time, so there is nothing to compare it against, and a cleared key\n            // is already rejected by the SecretName/SecretKey pairing check (ASPIRERADIUS087).\n            if (IsBicepExpression(reference.EnvVar.SecretKey) ||\n                RenderBicepLiteral(reference.EnvVar.SecretKey) is not { } currentSecretKey)","sourceCodeStart":1056,"sourceCodeEnd":1092,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs#L1056-L1092","documentation":"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.","triggerScenarios":"Running ConfigureRadiusInfrastructure callbacks that remove a SecuritySecrets resource still referenced by a container's credential environment variable ('{reference.Key}' on '{reference.ResourceName}').","commonSituations":"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.","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."],"exampleFix":"// before\ncallback: b =>\n{\n    b.RemoveResource(\"connection-secret\"); // container env var still points at it\n}\n\n// after\ncallback: b =>\n{\n    // keep the resource, or explicitly set the env var:\n    // b.SetEnvironmentVariable(\"frontend\", \"Connection__Password\", mySecretRef);\n}","handlingStrategy":"validation","validationCode":"// In a callback, only remove resources nothing depends on\nvar referencedSecrets = model.Resources\n    .SelectMany(r => r.Annotations.OfType<EnvironmentReferenceAnnotation>())\n    .Select(a => a.SecretName)\n    .ToHashSet();\nif (referencedSecrets.Contains(candidate.Name))\n    throw new InvalidOperationException($\"'{candidate.Name}' backs container credential env vars and cannot be removed.\");","typeGuard":null,"tryCatchPattern":"try { await builder.ExecuteCallbacksAsync(ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ASPIRERADIUS084\"))\n{\n    logger.LogError(ex, \"Callback removed a secret backing a container credential env var; keep it or set the env var explicitly.\");\n}","preventionTips":["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"],"tags":["radius","secrets","containers","callback","diagnostic-aspireradius084"],"backgroundTag":"resource-not-found","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}