{"record":{"id":"a103f1e4b8093318","repo":"OrchardCMS/OrchardCore","slug":"can-t-use-the-numeric-key-child-key-inside-an-object","errorCode":null,"errorMessage":"Can't use the numeric key '{child.Key}' inside an object.","messagePattern":"Can't use the numeric key '(.+?)' inside an object\\.","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/Internal/ConfigurationExtensions.cs","lineNumber":31,"sourceCode":"        {\n            throw new FormatException($\"Top level JSON element must be an object. Instead, {jsonNode.GetValueKind()} was found.\");\n        }\n\n        return jObject;\n    }\n\n    public static JsonNode ToJsonNode(this IConfiguration configuration)\n    {\n        JsonArray jArray = null;\n        JsonObject jObject = null;\n\n        foreach (var child in configuration.GetChildren())\n        {\n            if (int.TryParse(child.Key, out var index))\n            {\n                if (jObject is not null)\n                {\n                    throw new FormatException($\"Can't use the numeric key '{child.Key}' inside an object.\");\n                }\n\n                jArray ??= [];\n                if (index > jArray.Count)\n                {\n                    // Inserting null values is useful to override arrays items,\n                    // it allows to keep non null items at the right position.\n                    for (var i = jArray.Count; i < index; i++)\n                    {\n                        jArray.Add(null);\n                    }\n                }\n\n                if (child.GetChildren().Any())\n                {\n                    jArray.Add(ToJsonNode(child));\n                }\n                else","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/Internal/ConfigurationExtensions.cs#L13-L49","documentation":"ToJsonNode builds a JsonArray when child keys are numeric and a JsonObject otherwise. A numeric key inside an object-shaped level is invalid, so the method throws FormatException naming the offending key; mixing array items and object properties at one level is not representable.","triggerScenarios":"A configuration level contains both named keys and numeric keys, or a parent has a named key while a sibling has key '0' (e.g. 'Foo:Bar' plus 'Foo:0' patterns), triggering the jObject-not-null branch.","commonSituations":"Environment variables like App__Items__0 and App__Items__1 mixed with App__Name; hand-edited appsettings mixing arrays and objects at the same level; command-line args adding indexed keys to an object section.","solutions":["Make the level consistently array-shaped: use only numeric keys 0..n-1 for that section.","Or use only named keys and drop/renumber the numeric ones.","Locate the offending key with configuration.GetDebugView()/GetChildren() and fix the source provider (env vars, args, JSON).","Use ToJsonNode() and read as JsonNode, checking kind, if your data can be either shape."],"exampleFix":"// before\n\"App\": { \"Name\": \"x\", \"Items\": { \"0\": \"a\", \"1\": \"b\" } } // fine, but sibling 'App:0' breaks it\n// after\n\"App\": { \"Name\": \"x\", \"Items\": [\"a\", \"b\"] }","handlingStrategy":"validation","validationCode":"var keys = configuration.GetChildren().Select(c => c.Key).ToList();\nbool mixed = keys.Any(k => int.TryParse(k, out _)) && keys.Any(k => !int.TryParse(k, out _));\nif (mixed) throw new FormatException(\"Config level mixes numeric and named keys.\");","typeGuard":"bool IsArrayShaped(IConfiguration c) => c.GetChildren().All(ch => int.TryParse(ch.Key, out _));","tryCatchPattern":"try { var node = configuration.ToJsonNode(); }\ncatch (FormatException ex) when (ex.Message.Contains(\"numeric key\")) { /* fix provider keys or bind to typed model */ }","preventionTips":["Keep each config level either all-numeric or all-named","Avoid mixing env-var indexed keys with JSON object keys at the same path","Use typed binding (Get<T>()/Bind) for complex config shapes"],"tags":["configuration","json","format"],"backgroundTag":"schema-validation-failed","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}