OrchardCMS/OrchardCore · error · FormatException
Can't use the numeric key
Error message
Can't use the numeric key '{child.Key}' inside an object. What it means
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.
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.
Example fix
// before
"App": { "Name": "x", "Items": { "0": "a", "1": "b" } } // fine, but sibling 'App:0' breaks it
// after
"App": { "Name": "x", "Items": ["a", "b"] } Defensive patterns
Strategy: validation
Validate before calling
var keys = configuration.GetChildren().Select(c => c.Key).ToList();
bool mixed = keys.Any(k => int.TryParse(k, out _)) && keys.Any(k => !int.TryParse(k, out _));
if (mixed) throw new FormatException("Config level mixes numeric and named keys."); Type guard
bool IsArrayShaped(IConfiguration c) => c.GetChildren().All(ch => int.TryParse(ch.Key, out _));
Try / catch
try { var node = configuration.ToJsonNode(); }
catch (FormatException ex) when (ex.Message.Contains("numeric key")) { /* fix provider keys or bind to typed model */ } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Top level JSON element must be an object. Instead
- Can't use the non numeric key
- Top-level JSON element must be an object. Instead
- Could not parse the JSON document.
- A duplicate key ' ' was found.
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/a103f1e4b8093318.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/Internal/ConfigurationExtensions.cs:31
{
throw new FormatException($"Top level JSON element must be an object. Instead, {jsonNode.GetValueKind()} was found.");
}
return jObject;
}
public static JsonNode ToJsonNode(this IConfiguration configuration)
{
JsonArray jArray = null;
JsonObject jObject = null;
foreach (var child in configuration.GetChildren())
{
if (int.TryParse(child.Key, out var index))
{
if (jObject is not null)
{
throw new FormatException($"Can't use the numeric key '{child.Key}' inside an object.");
}
jArray ??= [];
if (index > jArray.Count)
{
// Inserting null values is useful to override arrays items,
// it allows to keep non null items at the right position.
for (var i = jArray.Count; i < index; i++)
{
jArray.Add(null);
}
}
if (child.GetChildren().Any())
{
jArray.Add(ToJsonNode(child));
}
elseView on GitHub (pinned to 4306c0717f)