microsoft/aspire · error · InvalidOperationException

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

Error message

Secret store '{storeName}' references a manifest at '{manifestPath}' that uses a non-scalar YAML mapping key. Provide a plain SealedSecret manifest with scalar keys.

What it means

YAML mapping keys in a SealedSecret manifest must be scalars. A key that is itself a mapping or sequence (complex keys) cannot be interpreted as a field name, so the validator rejects the document as non-plain.

Solutions

  1. Replace complex keys with plain scalar strings
  2. Simplify the mapping structure so each key is a simple identifier
  3. Regenerate the manifest from kubeseal or the intended tool so keys are scalars

Example fix

// before
? [environment, region]
: prod
// after
environment-region: prod
Defensive patterns

Strategy: validation

Validate before calling

var yaml = new YamlDotNet.RepresentationModel.YamlStream();
yaml.Load(new StringReader(File.ReadAllText(manifestPath)));
var root = (YamlDotNet.RepresentationModel.YamlMappingNode)yaml.Documents[0].RootNode;
foreach (var kv in root)
    if (kv.Key.NodeType != YamlDotNet.RepresentationModel.YamlNodeType.Scalar)
        throw new InvalidOperationException("Manifest has non-scalar keys");

Prevention

When it happens

Trigger: ValidateStructure -> RegisterNodeWithParent, when the current frame expects a key and the incoming event is not a Scalar — e.g. `? [a, b] : value` or a nested-map used as a key.

Common situations: Machine-generated YAML with complex keys; flow-style `? {..} : ..` syntax; copy-pasted YAML using multi-line or structured keys.

Related errors


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

Appendix: source

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

    private static void RegisterNodeWithParent(
        string storeName, string manifestPath, ParsingEvent yamlEvent, Stack<MappingFrame> stack)
    {
        if (stack.Count == 0)
        {
            return;
        }

        var frame = stack.Peek();
        if (frame.IsSequence)
        {
            return;
        }

        if (frame.ExpectsKey)
        {
            if (yamlEvent is not Scalar scalar)
            {
                throw CreateInvalidManifestException(
                    storeName,
                    manifestPath,
                    "uses a non-scalar YAML mapping key. Provide a plain SealedSecret manifest with scalar keys.");
            }

            var key = scalar.Value;
            if (string.Equals(key, "<<", StringComparison.Ordinal))
            {
                throw CreateInvalidManifestException(
                    storeName,
                    manifestPath,
                    "uses YAML merge keys. Provide a self-contained SealedSecret manifest without anchors, aliases, or merge keys.");
            }

            // YAML allows duplicate keys, and some high-level readers keep the last value. For a
            // security gate that rejects plaintext-capable fields, last-wins semantics would let a
            // document advertise `kind: SealedSecret` first and then override it with `kind: Secret`.
            if (!frame.Keys.Add(key))

View on GitHub (pinned to 25830f84bd)