microsoft/aspire · error · InvalidOperationException
ASPIRERADIUS040
ASPIRERADIUS040
Error message
Secret store '{store.Name}' of type '{store.Type.ToRadiusTypeString()}' is missing the required key '{required}'. Diagnostic: ASPIRERADIUS040. What it means
ASPIRERADIUS040 enforces type-aware required keys: each RadiusSecretStoreType has a set of keys Radius requires (e.g. certificate needs 'tls.crt' and 'tls.key'); RequiredKeys() returns them and ValidateStore throws when a required key is missing from the declared key set. Generic stores require none.
Solutions
- Add the missing required key literal exactly (see RequiredKeys(), e.g. 'tls.crt' and 'tls.key' for Certificate).
- Switch the store type to Generic if you do not intend to provide the specialized keys.
- Check RequiredKeys() for your store.Type and make your population code emit all of them.
Example fix
// before
var store = builder.AddRadiusSecretStore("cert", type: RadiusSecretStoreType.Certificate)
.WithData();
store.WithData().Add("tls.crt", crtParam);
// after
store.WithData().Add("tls.crt", crtParam).Add("tls.key", keyParam); Defensive patterns
Strategy: validation
Validate before calling
foreach (var required in store.Type.RequiredKeys())
if (!declaredKeys.Contains(required, StringComparer.Ordinal))
throw new InvalidOperationException($"{store.Name} missing required key {required}"); Try / catch
try { /* validation runs */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("ASPIRERADIUS040")) { /* add the missing required key */ } Prevention
- Consult store.Type.RequiredKeys() and emit every literal it returns
- Use Generic type when you don't intend to supply specialized keys
- Keep key names exactly as Radius expects ('tls.crt', 'tls.key', etc.)
When it happens
Trigger: Declaring a store of type Certificate or BasicAuthentication (or AzureWorkloadIdentity/AwsIrsa) but not declaring its required keys — e.g. a certificate store without 'tls.crt'/'tls.key' — then validating.
Common situations: Using a specialized store type while populating it as if it were generic; renaming keys away from the Radius-required literals; partial migration from a generic store sample.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/f037c04641fffd23.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Secrets/RadiusSecretStoreValidation.cs:158
{
var seen = new HashSet<string>(StringComparer.Ordinal);
foreach (var key in population.Keys)
{
if (!seen.Add(key))
{
throw new InvalidOperationException(
$"Secret store '{store.Name}' declares the key '{key}' more than once. " +
"Diagnostic: ASPIRERADIUS043.");
}
}
}
// ASPIRERADIUS040 — type-aware required keys.
foreach (var required in store.Type.RequiredKeys())
{
if (!declaredKeys.Contains(required, StringComparer.Ordinal))
{
throw new InvalidOperationException(
$"Secret store '{store.Name}' of type '{store.Type.ToRadiusTypeString()}' is missing " +
$"the required key '{required}'. Diagnostic: ASPIRERADIUS040.");
}
}
// ASPIRERADIUS042 / ASPIRERADIUS047 — inline bindings must be secret and use valid encoding.
if (population.HasInlineData)
{
foreach (var (key, binding) in population.Data)
{
if (!binding.Parameter.Secret)
{
throw new InvalidOperationException(
$"Secret store '{store.Name}' binds key '{key}' to the non-secret parameter " +
$"'{binding.Parameter.Name}'. Bind a parameter created with secret: true. " +
"Diagnostic: ASPIRERADIUS042.");
}
View on GitHub (pinned to 25830f84bd)