microsoft/aspire · critical · InvalidOperationException
Secret store ' ' references a manifest at ' ' that contains…
Error message
Secret store '{storeName}' references a manifest at '{manifestPath}' that contains top-level plaintext Kubernetes Secret fields ('data' or 'stringData'). Seal those values under spec.encryptedData instead. What it means
The manifest is a valid SealedSecret, but plaintext-capable Secret fields were found: either top-level 'data'/'stringData', or plaintext-capable 'spec.template.data'/'spec.template.stringData' entries. Including cleartext in a SealedSecret defeats the sealing guarantee, so the loader rejects it to prevent leaking secrets into the published manifest.
Solutions
- Remove top-level 'data'/'stringData' from the manifest entirely.
- Seal all secret values into 'spec.encryptedData' with kubeseal instead of template.data/stringData.
- Regenerate the manifest from the original Secret using kubeseal so no plaintext fields survive.
- Review spec.template — keep only non-secret metadata (labels, annotations, type), no data fields.
Example fix
# before: plaintext left in manifest
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
spec:
template:
data:
password: plaintext
encryptedData:
password: AgB...
# after
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
spec:
encryptedData:
password: AgB... Defensive patterns
Strategy: validation
Validate before calling
// Fail CI on plaintext leak
bool leaks = root["data"] != null || root["stringData"] != null
|| root["spec"]?["template"]?["data"] != null
|| root["spec"]?["template"]?["stringData"] != null;
if (leaks) throw new InvalidOperationException("Manifest contains plaintext secret fields"); Try / catch
catch (Exception ex) when (ex.Message.Contains("plaintext"))
{
// remove data/stringData fields and re-seal values into spec.encryptedData
} Prevention
- Never paste a plain Secret's data block into a sealed manifest.
- Keep spec.template limited to non-secret metadata.
- Scan manifests for 'data:'/'stringData:' in CI as a leak gate.
- Always generate sealed manifests via kubeseal, not by hand.
When it happens
Trigger: ReadMetadataFromRoot finds a 'data' or 'stringData' node at the root, or a spec.template mapping where ContainsPlaintextTemplateData(template, "data"|"stringData") is true.
Common situations: Copy-pasting a plain Secret's data block into the sealed manifest; kubeseal versions/workflows that emit template.data; manually merging a Secret template with encryptedData and leaving plaintext keys; partial sealing where some values were left unencrypted.
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
- ASPIRERADIUS063
- Secret store ' ' references a manifest at ' ' that contains…
- Aspire skills archive entry
- Aspire skills archive entry
- Aspire skills archive entry
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/b5936cbf9d6e761d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Secrets/SealedSecretManifest.cs:188
$"Bitnami SealedSecret (expected 'kind: SealedSecret' and 'apiVersion: {SupportedApiVersion}'; found " +
$"kind '{kind ?? "<none>"}', apiVersion '{apiVersion ?? "<none>"}'). Diagnostic: ASPIRERADIUS044.");
}
if (TryGetNode(root, "data", out _) || TryGetNode(root, "stringData", out _))
{
throw CreateInvalidManifestException(
storeName,
manifestPath,
"contains top-level plaintext Kubernetes Secret fields ('data' or 'stringData'). Seal those values under spec.encryptedData instead.");
}
if (TryGetNode(root, "spec", out var specNode) &&
specNode is YamlMappingNode spec &&
TryGetNode(spec, "template", out var templateNode) &&
templateNode is YamlMappingNode template &&
(ContainsPlaintextTemplateData(template, "data") || ContainsPlaintextTemplateData(template, "stringData")))
{
throw CreateInvalidManifestException(
storeName,
manifestPath,
"contains plaintext-capable spec.template.data or spec.template.stringData values. Seal secret material under spec.encryptedData instead.");
}
// A `kubectl.kubernetes.io/last-applied-configuration` annotation records the full JSON of a
// previously-applied object. Unlike spec.encryptedData it is NOT encrypted, so a plaintext
// Secret embedded there (top-level metadata, or the templated Secret's metadata) would be
// copied verbatim into publish artifacts and re-applied — defeating sealing. Reject it.
RejectPlaintextLastAppliedAnnotation(storeName, manifestPath, root);
// Runs after the leak gates above so a manifest that both leaks cleartext and has a malformed
// payload still reports the more specific ASPIRERADIUS063/plaintext diagnostic.
ValidateEncryptedData(storeName, manifestPath, root);
if (!TryGetNode(root, "metadata", out var metadataNode) || metadataNode is not YamlMappingNode metadata)
{
throw CreateInvalidManifestException(View on GitHub (pinned to 25830f84bd)