{"record":{"id":"a865c14bb2beac8a","repo":"microsoft/aspire","slug":"manifest-field-dictionaries-must-use-string-keys","errorCode":null,"errorMessage":"Manifest field dictionaries must use string keys.","messagePattern":"Manifest field dictionaries must use string keys\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Kubernetes/KubernetesManifestResource.cs","lineNumber":243,"sourceCode":"            JsonValueKind.True => true,\n            JsonValueKind.False => false,\n            JsonValueKind.Number when element.TryGetInt64(out var longValue) => longValue,\n            JsonValueKind.Number => element.GetDouble(),\n            JsonValueKind.Array => element.EnumerateArray().Select(NormalizeJsonElement).ToList(),\n            JsonValueKind.Object => element.EnumerateObject().ToDictionary(prop => prop.Name, prop => NormalizeJsonElement(prop.Value), StringComparer.Ordinal),\n            _ => throw new ArgumentException($\"Unsupported JSON value kind '{element.ValueKind}'.\", nameof(element))\n        };\n    }\n\n    private static Dictionary<string, object?> NormalizeDictionary(IDictionary dictionary)\n    {\n        var result = new Dictionary<string, object?>(StringComparer.Ordinal);\n\n        foreach (DictionaryEntry entry in dictionary)\n        {\n            if (entry.Key is not string key)\n            {\n                throw new ArgumentException(\"Manifest field dictionaries must use string keys.\");\n            }\n\n            result[key] = NormalizeManifestValue(entry.Value);\n        }\n\n        return result;\n    }\n\n    private static List<object?> NormalizeEnumerable(IEnumerable enumerable)\n    {\n        var result = new List<object?>();\n\n        foreach (var item in enumerable)\n        {\n            result.Add(NormalizeManifestValue(item));\n        }\n\n        return result;","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Kubernetes/KubernetesManifestResource.cs#L225-L261","documentation":"Dictionaries passed as manifest field values must have string keys because JSON objects only support string keys. When an IDictionary entry's key is not a string (e.g. int, enum, or a custom key type), the normalizer throws this ArgumentException (note: without a parameter name).","triggerScenarios":"Calling WithField with a Dictionary<int, ...>, Dictionary<MyEnum, ...>, Hashtable, or any IDictionary whose keys are not strings. Also occurs when passing a dictionary that got boxed into IDictionary with non-string keys at runtime.","commonSituations":"Using enums as lookup keys, building maps from parsed data with numeric keys, or passing a Hashtable copied from legacy code. Developers expect keys to be auto-stringified, but the library requires explicit strings.","solutions":["Convert the dictionary to Dictionary<string, object?> with keys serialized via ToString() before passing","Use StringEnumConverters or map enum keys to their string names explicitly","For numeric keys, prefix/convert them to strings (e.g. key.ToString(CultureInfo.InvariantCulture))"],"exampleFix":"// before\nvar replicas = new Dictionary<WorkloadKind, int> { [WorkloadKind.Web] = 3 };\nmanifest.WithField(\"spec.replicasByKind\", replicas);\n// after\nvar replicas = new Dictionary<string, object?> { [WorkloadKind.Web.ToString()] = 3 };\nmanifest.WithField(\"spec.replicasByKind\", replicas);","handlingStrategy":"validation","validationCode":"bool allStringKeys = dict is IDictionary d && d.Keys.Cast<object>().All(k => k is string);","typeGuard":"static bool HasStringKeys(IDictionary d) => d.Keys.Cast<object>().All(k => k is string);","tryCatchPattern":"try { manifest.WithField(path, dict); } catch (ArgumentException ex) when (ex.Message.Contains(\"string keys\")) { var fixedDict = dict.Keys.Cast<object>().ToDictionary(k => k.ToString()!, k => dict[k]); manifest.WithField(path, fixedDict); }","preventionTips":["Always build manifest dictionaries as Dictionary<string, object?>","Convert enum or numeric keys to strings before adding","Avoid Hashtable for manifest fields"],"tags":["kubernetes","manifest","dictionary","json"],"backgroundTag":"invalid-argument-value","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"}