{"record":{"id":"eb0bcbf9f821c19d","repo":"microsoft/aspire","slug":"cannot-set-nested-manifest-field-path-because-segment","errorCode":null,"errorMessage":"Cannot set nested manifest field '{path}' because '{segment}' already has a scalar value.","messagePattern":"Cannot set nested manifest field '(.+?)' because '(.+?)' already has a scalar value\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Kubernetes/KubernetesManifestResource.cs","lineNumber":125,"sourceCode":"        {\n            throw new ArgumentException(\"Use the dedicated manifest API to configure apiVersion, kind, and metadata fields.\", nameof(path));\n        }\n\n        return segments;\n    }\n\n    private static void SetField(Dictionary<string, object?> fields, ReadOnlySpan<string> segments, string path, object? value)\n    {\n        var current = fields;\n\n        for (var i = 0; i < segments.Length - 1; i++)\n        {\n            var segment = segments[i];\n            if (current.TryGetValue(segment, out var child))\n            {\n                if (child is not Dictionary<string, object?> childFields)\n                {\n                    throw new ArgumentException($\"Cannot set nested manifest field '{path}' because '{segment}' already has a scalar value.\", nameof(path));\n                }\n\n                current = childFields;\n            }\n            else\n            {\n                var childFields = new Dictionary<string, object?>(StringComparer.Ordinal);\n                current[segment] = childFields;\n                current = childFields;\n            }\n        }\n\n        current[segments[^1]] = value;\n    }\n\n    internal static object? NormalizeManifestValue(object? value)\n    {\n        return value switch","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Kubernetes/KubernetesManifestResource.cs#L107-L143","documentation":"SetField walks the dotted path through nested dictionaries of the manifest. If an intermediate segment exists but holds a scalar (non-dictionary) value, deeper nesting is impossible, so it throws ArgumentException naming the offending path and segment.","triggerScenarios":"Calling WithField(\"spec.replicas.count\", 3) after \"spec.replicas\" was previously set to a scalar like 3 via WithField(\"spec.replicas\", 3); any path that conflicts with an earlier scalar assignment on the same prefix.","commonSituations":"Multiple WithField calls where one treats a key as an object and another as a value; merging field overrides from config where the same prefix is assigned different shapes.","solutions":["Remove or change the earlier WithField call that assigned a scalar to the conflicting segment so it can hold a nested object.","Restructure the field paths so each key is consistently either a leaf value or a parent object.","If the value should be an object, set the full nested value in a single call at the parent path instead of nesting beneath a scalar."],"exampleFix":"// before\nresource.WithField(\"spec.replicas\", 3);\nresource.WithField(\"spec.replicas.min\", 1); // throws\n// after\nresource.WithField(\"spec.replicas\", new Dictionary<string, object?> { [\"min\"] = 1 });","handlingStrategy":"validation","validationCode":"static bool IsScalarConflict(IEnumerable<string> appliedPaths, string newPath)\n{\n    var segments = newPath.Split('.');\n    return appliedPaths.Any(p =>\n    {\n        var s = p.Split('.');\n        return s.Length < segments.Length && s.SequenceEqual(segments.Take(s.Length));\n    });\n}","typeGuard":"static bool CanNest(object? existing) => existing is null or Dictionary<string, object?>;","tryCatchPattern":"try\n{\n    resource.WithField(path, value);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"already has a scalar value\"))\n{\n    // A previous WithField assigned a scalar on this prefix; restructure the paths.\n}","preventionTips":["Design the manifest field shape up front so each key is either a leaf or a parent, never both.","Keep a registry of applied field paths and detect prefix conflicts before applying new ones.","Set whole nested objects in a single WithField call rather than mixing scalar and object assignments on the same prefix."],"tags":["kubernetes","manifest","type-conflict","nested-field"],"backgroundTag":"type-mismatch","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}