microsoft/aspire · error · InvalidOperationException

Secret store ' ' references a manifest at ' ' that has a…

Error message

Secret store '{storeName}' references a manifest at '{manifestPath}' that has a spec.encryptedData entry '{key}' that is not a non-empty standard-base64 encoded sealed value. Seal the secret with kubeseal instead of writing the value by hand.

What it means

When reading a Radius sealed-secret manifest, each spec.encryptedData entry must be a non-empty string that is valid standard (padded) base64, because it represents ciphertext produced by kubeseal. This error is thrown when an entry is missing, empty, not a scalar, or not standard base64, indicating the value was written by hand rather than sealed.

Solutions

  1. Re-seal the secret with `kubeseal < secret.yaml > sealed.yaml` so encryptedData contains genuine kubeseal output
  2. Check each encryptedData value decodes with Convert.FromBase64String (standard alphabet, padding required); fix truncated or whitespace-corrupted values
  3. Quote the value in YAML so scalar types like `true` remain strings
  4. Ensure the value is non-empty and was copied completely (no truncation at line-wrap)

Example fix

// before
spec:
  encryptedData:
    password: my-plaintext-password
// after
# echo -n 'my-plaintext-password' | kubeseal --raw > cipher.b64
spec:
  encryptedData:
    password: "AgBj3mQ9...=="
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidEncryptedDataValue(string? v) =>
    !string.IsNullOrEmpty(v) && Convert.TryFromBase64String(v, new byte[(v.Length * 3) / 4 + 3], out _);

Type guard

bool IsStandardBase64String(object? v) => v is string s && !string.IsNullOrEmpty(s) && Convert.TryFromBase64String(s, new byte[s.Length], out _);

Prevention

When it happens

Trigger: ReadMetadataFromRoot -> ValidateEncryptedData encounters an encryptedData value that is empty, a non-scalar YAML node (e.g. a boolean like `true`), or a string that is not standard base64 (missing padding, URL-safe characters, or arbitrary text).

Common situations: Developers hand-editing a SealedSecret manifest and typing a plaintext or hex value; copying ciphertext that lost base64 padding; using URL-safe base64 from non-kubeseal tooling; YAML unquoting values like `true` into booleans.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/dd54d54db8e207e7. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Radius/Secrets/SealedSecretManifest.cs:296

        foreach (var (keyNode, valueNode) in encryptedData.Children)
        {
            // ValidateStructure already rejects non-scalar mapping keys, so the key is a scalar here;
            // read it defensively for the diagnostic message only.
            var key = (keyNode as YamlScalarNode)?.Value ?? "<non-scalar>";

            // kubeseal writes each value with Go's base64.StdEncoding and the controller decodes it the
            // same way, so anything that is not a standard-base64 scalar cannot be a sealed value. This
            // does not prove the value is ciphertext (plaintext can be valid base64), but it fails
            // closed on the shapes the CRD never produces: nested mappings/sequences, empty/whitespace
            // values, and most implicit non-string scalars (`123`, `~`). It cannot reject a short plain
            // scalar that happens to be valid base64 (`true`), and a minimum length is deliberately not
            // enforced because the ciphertext length is not a documented part of the format.
            // https://github.com/bitnami-labs/sealed-secrets/blob/main/pkg/apis/sealedsecrets/v1alpha1/sealedsecret_expansion.go
            if (valueNode is not YamlScalarNode { Value: { Length: > 0 } value } ||
                !IsStandardBase64(value))
            {
                throw CreateInvalidManifestException(
                    storeName,
                    manifestPath,
                    $"has a spec.encryptedData entry '{key}' that is not a non-empty standard-base64 encoded sealed " +
                    "value. Seal the secret with kubeseal instead of writing the value by hand.");
            }
        }
    }

    private static bool IsStandardBase64(string value) =>
        // Base64.IsValid validates without allocating a decode buffer (the ciphertext can be large).
        // It ignores whitespace, so require a non-zero decoded length to reject a whitespace-only value.
        Base64.IsValid(value, out var decodedLength) && decodedLength > 0;

    private static bool ContainsPlaintextTemplateData(YamlMappingNode template, string field) =>
        TryGetNode(template, field, out var value) && HasContent(value);

    // The annotation key `kubectl apply` uses to stash the last-applied object JSON.
    private const string LastAppliedConfigurationAnnotation = "kubectl.kubernetes.io/last-applied-configuration";

View on GitHub (pinned to 25830f84bd)