{"record":{"id":"b7e36d8196b7388c","repo":"microsoft/aspire","slug":"aspireradius074","errorCode":"ASPIRERADIUS074","errorMessage":"Radius resource '{credential.Consumer.BicepIdentifier}' reads its '{credential.PropertyName}' from the '{RadiusResourceTypes.SecuritySecrets}' resource '{credential.OriginalSecretIdentifier}', but a ConfigureRadiusInfrastructure callback removed it. The property is required, so the deployment would be rejected. Keep the secret, or point '{credential.PropertyName}' at a secret of your own. Diagnostic: ASPIRERADIUS074.","messagePattern":"Radius resource '(.+?)' reads its '(.+?)' from the '(.+?)' resource '(.+?)', but a ConfigureRadiusInfrastructure callback removed it\\. The property is required, so the deployment would be rejected\\. Keep the secret, or point '(.+?)' at a secret of your own\\. Diagnostic: ASPIRERADIUS074\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs","lineNumber":946,"sourceCode":"                continue;\n            }\n\n            // The callback took ownership of the property, so this relationship is no longer the\n            // publisher's to enforce — last-write-wins, exactly as for container env values and\n            // projected type properties. This has to be decided *before* the checks below: those\n            // reject removing the secret or changing the credential, which are legitimate once the\n            // consumer no longer reads from it. The credential schema properties are internal, so\n            // the typed surface offers no way to reassign one, but the `ProvisionableProperties`\n            // dictionary inherited from Azure.Provisioning is public and reaches the same values.\n            if (credential.Consumer.GetSchemaProperty(credential.PropertyName) is not { } currentProperty ||\n                !string.Equals(RenderBicepValue(currentProperty), credential.OriginalPropertyValue, StringComparison.Ordinal))\n            {\n                continue;\n            }\n\n            if (!liveSecrets.Contains(credential.Secret))\n            {\n                throw new InvalidOperationException(\n                    $\"Radius resource '{credential.Consumer.BicepIdentifier}' reads its '{credential.PropertyName}' from \" +\n                    $\"the '{RadiusResourceTypes.SecuritySecrets}' resource '{credential.OriginalSecretIdentifier}', but a \" +\n                    $\"ConfigureRadiusInfrastructure callback removed it. The property is required, so the deployment would \" +\n                    $\"be rejected. Keep the secret, or point '{credential.PropertyName}' at a secret of your own. \" +\n                    $\"Diagnostic: ASPIRERADIUS074.\");\n            }\n\n            // The consumer still reads this secret, so the entry carrying the credential has to\n            // survive intact. Unlike a container env secret — whose only reader is the variable that\n            // points at it, so a callback replacing the value is self-consistent — this value is\n            // handed to the *recipe* that provisions the server, while the matching credential was\n            // already composed into every consumer's connection string from Aspire's own parameter.\n            // Removing it prevents the recipe from starting; changing it provisions a server with a\n            // password no consumer was told about, which fails only as an authentication error at\n            // runtime. Neither can be repaired here, so both are rejected.\n            if (!credential.Secret.Data.TryGetValue(credential.SecretKey, out var liveEntry))\n            {\n                throw new InvalidOperationException(","sourceCodeStart":928,"sourceCodeEnd":964,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Radius/Publishing/RadiusInfrastructureBuilder.cs#L928-L964","documentation":"Aspire generates a Security/secrets resource supplying required credential properties for Radius resources, and consumers' Bicep properties are wired to it. A ConfigureRadiusInfrastructure callback removed that secret resource from the model; since the property is required, Radius would reject the deployment, so the builder throws early with ASPIRERADIUS074.","triggerScenarios":"Inside a ConfigureRadiusInfrastructure callback, removing (or filtering out) the generated SecuritySecrets resource that a credential-bearing property of another Radius resource still references (tracked via credential.OriginalSecretIdentifier).","commonSituations":"Callback code that deletes all generated helper resources to 'clean up' the Bicep; a builder loop that removes secrets it does not recognize; overzealous resource filtering that breaks credential references.","solutions":["Stop removing that secret resource in the ConfigureRadiusInfrastructure callback.","Keep the resource but repoint the consuming property's '{PropertyName}' at a secret you create yourself in the callback.","Only remove generated secrets when you also replace every credential property that referenced them."],"exampleFix":"// before\ncallback: b =>\n{\n    b.RemoveResource(\"admin-password-secret\"); // breaks consumers\n}\n\n// after\ncallback: b =>\n{\n    // keep the generated secret, or replace it AND repoint the consumer:\n    // b.SetProperty(\"cache\", \"password\", myOwnSecretRef);\n}","handlingStrategy":"validation","validationCode":"// Inside ConfigureRadiusInfrastructure, never remove generated secret resources\ncallback: b =>\n{\n    foreach (var name in resourcesToRemove)\n    {\n        if (b.GetResource(name) is { IsGeneratedCredentialSecret: true })\n            throw new InvalidOperationException($\"Refusing to remove credential secret '{name}' — it is consumed by a required property.\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try { await builder.ExecuteCallbacksAsync(ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ASPIRERADIUS074\"))\n{\n    logger.LogError(ex, \"A callback removed a required credential secret; restore it or repoint the property.\");\n}","preventionTips":["Never delete generated Security/secrets resources in ConfigureRadiusInfrastructure callbacks","Filter callback removals by explicit allow-list, not by resource type","If replacing a secret, repoint every consumer property to your own secret in the same callback"],"tags":["radius","bicep","secrets","callback","diagnostic-aspireradius074"],"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"}