microsoft/aspire · error · InvalidOperationException
ASPIRERADIUS061
ASPIRERADIUS061
Error message
The Secret '{metadata.Namespace}/{metadata.Name}' materialized by sealed secret store '{store.Name}' is missing the declared key(s) {string.Join(", ", missing.Select(k => $"'{k}'"))}. Ensure the sealed manifest's spec.encryptedData contains every key declared with WithSealedSecret. Diagnostic: ASPIRERADIUS061. What it means
After applying a SealedSecret, the step re-reads the materialized Kubernetes Secret and compares its data keys against the keys declared via WithSealedSecret. If the Secret exists but is missing one or more declared keys, ASPIRERADIUS061 is thrown: the sealed manifest's spec.encryptedData did not include every declared key, so the controller materialized an incomplete Secret.
Solutions
- Re-generate the sealed manifest so spec.encryptedData contains every key declared with WithSealedSecret, then re-run deploy.
- Compare the missing key names from the message against spec.encryptedData in the sealed manifest and add the missing entries (seal them with kubeseal).
- Ensure the declared keys in WithSealedSecret exactly match (case included) the keys in the source Secret you sealed.
Example fix
// before
store.WithSealedSecret("username").WithSealedSecret("password");
// manifest encryptedData only contains 'username'
// after
// seal both keys: kubeseal --secret <secret-with-username-and-password> ...
// spec.encryptedData now contains username AND password Defensive patterns
Strategy: validation
Validate before calling
// Before deploy: assert the sealed manifest covers all declared keys
var manifest = LoadYaml(manifestPath);
var sealedKeys = ((IDictionary<object, object>)manifest["spec"]["encryptedData"]).Keys.Select(k => k.ToString()).ToHashSet();
var missing = declaredKeys.Except(sealedKeys).ToList();
if (missing.Count > 0) throw new InvalidOperationException($"sealed manifest missing keys: {string.Join(", ", missing)}"); Prevention
- Regenerate the sealed manifest every time WithSealedSecret declarations change.
- Keep the source Secret, WithSealedSecret keys, and spec.encryptedData keys in one documented checklist.
- Never hand-edit spec.encryptedData; always seal with kubeseal from the source secret.
When it happens
Trigger: ApplyStoreAsync, after waiting for the SealedSecret controller to sync (within store.MaterializationTimeout), finds FindMissingDeclaredKeys(store.Population.Keys, dataKeys) non-empty — i.e. the Secret on the cluster lacks keys that were registered with WithSealedSecret.
Common situations: Regenerating the sealed manifest after adding a new WithSealedSecret key but not re-encrypting/re-applying spec.encryptedData; kubeseal run against an older manifest; the encryptedData block edited or truncated by hand; YAML key typos between the declaration and the sealed manifest.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- ASPIRERADIUS046
- ASPIRERADIUS058
- ASPIRERADIUS067
- Kubernetes namespace
- A ConfigureRadiusInfrastructure callback left container
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/33257f4c349cdaf4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Publishing/SealedSecretApplyStep.cs:159
ct => SecretExistsAsync(metadata.Namespace, metadata.Name, kubeContext, ct),
cancellationToken).ConfigureAwait(false);
// The SealedSecret controller can report Synced=True and create a Secret that is missing keys
// the store declares (e.g. the manifest's encryptedData omits a key, or a stale Secret from a
// prior seal is reused). The declared keys are the contract downstream recipeConfig/envSecrets
// wiring reads, so verify each one is present in the materialized Secret before rad deploy.
if (store.Population.Keys.Count > 0)
{
var dataKeys = await InvokeProbeWithRemainingBudgetAsync(
ct => GetSecretDataKeysAsync(metadata.Namespace, metadata.Name, kubeContext, ct),
RemainingBudget(deadline),
cancellationToken,
() => CreateOperationTimeoutException(store.Name, metadata.Namespace, metadata.Name, "verify", store.MaterializationTimeout))
.ConfigureAwait(false);
var missing = FindMissingDeclaredKeys(store.Population.Keys, dataKeys);
if (missing.Count > 0)
{
throw new InvalidOperationException(
$"The Secret '{metadata.Namespace}/{metadata.Name}' materialized by sealed secret store " +
$"'{store.Name}' is missing the declared key(s) {string.Join(", ", missing.Select(k => $"'{k}'"))}. " +
"Ensure the sealed manifest's spec.encryptedData contains every key declared with WithSealedSecret. " +
"Diagnostic: ASPIRERADIUS061.");
}
}
}
/// <summary>Returns the declared keys that are absent from the materialized Secret's data keys, preserving declared order.</summary>
internal static IReadOnlyList<string> FindMissingDeclaredKeys(IEnumerable<string> declaredKeys, IReadOnlySet<string> presentKeys) =>
declaredKeys.Where(k => !presentKeys.Contains(k)).ToList();
// Prefers the self-contained published artifact (sealed-secrets/<store>/<file> under the
// emitted app.bicep) so publish-then-deploy across machines works; falls back to the author
// source path for the in-place same-run case.
private static string ResolveManifestPath(string storeOutputDir, string storeName, string sourceManifestPath)
{
var artifact = SealedSecretArtifact.ResolvePath(storeOutputDir, storeName, sourceManifestPath);View on GitHub (pinned to 25830f84bd)