{"record":{"id":"5d488780615beb7c","repo":"microsoft/aspire","slug":"use-the-dedicated-manifest-api-to-configure-apiversion-kind","errorCode":null,"errorMessage":"Use the dedicated manifest API to configure apiVersion, kind, and metadata fields.","messagePattern":"Use the dedicated manifest API to configure apiVersion, kind, and metadata fields\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Kubernetes/KubernetesManifestResource.cs","lineNumber":108,"sourceCode":"\n        SetField(Fields, segments, path, NormalizeManifestValue(value));\n\n        return this;\n    }\n\n    private static string[] ParseFieldPath(string path)\n    {\n        ArgumentException.ThrowIfNullOrWhiteSpace(path);\n\n        var segments = path.Split('.', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);\n        if (segments.Length == 0)\n        {\n            throw new ArgumentException(\"Manifest field path must contain at least one segment.\", nameof(path));\n        }\n\n        if (segments[0] is \"apiVersion\" or \"kind\" or \"metadata\")\n        {\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                }","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Kubernetes/KubernetesManifestResource.cs#L90-L126","documentation":"ParseFieldPath rejects field paths whose first segment is apiVersion, kind, or metadata. Those parts of a Kubernetes manifest are managed by the dedicated manifest API (WithApiVersion/WithKind/metadata settings), so overriding them via generic field paths is disallowed to keep the manifest consistent.","triggerScenarios":"Calling WithField(\"apiVersion\", ...), WithField(\"kind\", ...), or any path starting with \"metadata\" (e.g. \"metadata.labels.app\") on a Kubernetes manifest resource.","commonSituations":"Porting raw YAML patch code where labels/annotations were set under metadata; developers assuming WithField is a universal JSON-patch mechanism.","solutions":["Use WithKind and WithApiVersion (or the equivalent dedicated manifest API) to set kind and apiVersion.","Use the dedicated metadata API (e.g. WithLabel/WithAnnotation style methods) instead of paths under \"metadata\".","Reserve WithField for fields under spec or other non-reserved top-level segments."],"exampleFix":"// before\nresource.WithField(\"metadata.labels.app\", \"web\");\n// after\nresource.WithLabel(\"app\", \"web\");","handlingStrategy":"validation","validationCode":"var reserved = new[] { \"apiVersion\", \"kind\", \"metadata\" };\nif (reserved.Contains(path.Split('.', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()))\n{\n    throw new ArgumentException($\"Field path '{path}' targets reserved manifest fields; use the dedicated manifest API.\", nameof(path));\n}","typeGuard":"static bool IsReservedManifestPath(string path) =>\n    path.Split('.', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() is \"apiVersion\" or \"kind\" or \"metadata\";","tryCatchPattern":"try\n{\n    resource.WithField(path, value);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"dedicated manifest API\"))\n{\n    // Route apiVersion/kind/metadata updates through WithApiVersion/WithKind/label APIs\n}","preventionTips":["Remember WithField is for spec-level and custom fields only.","Use WithKind/WithApiVersion and the metadata/label APIs for reserved sections.","Centralize field path constants and mark reserved prefixes in one place."],"tags":["kubernetes","manifest","reserved-field","argument"],"backgroundTag":"unsupported-operation","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}