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

  1. Remove top-level 'data'/'stringData' from the manifest entirely.
  2. Seal all secret values into 'spec.encryptedData' with kubeseal instead of template.data/stringData.
  3. Regenerate the manifest from the original Secret using kubeseal so no plaintext fields survive.
  4. 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

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


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)