OrchardCMS/OrchardCore · error · FormatException
Top level JSON element must be an object. Instead
Error message
Top level JSON element must be an object. Instead, {jsonNode.GetValueKind()} was found. What it means
ToJsonObject converts an IConfiguration tree to a JsonObject by first building a JsonNode. Because configuration is expected to be a flat key/value mapping, the root node must be an object; if the root turned out to be an array or value, the method throws FormatException.
Solutions
- Ensure the configuration root only has named (non-numeric) keys; rename numeric keys to named ones.
- Call ToJsonObject on a specific object-shaped section: configuration.GetSection("MyObject").ToJsonObject().
- If the data is genuinely an array, use ToJsonNode() and handle the JsonArray result instead.
- Sanitize provider keys (e.g. environment variables) so indexed entries aren't at the root.
Example fix
// before
var obj = envDrivenConfig.ToJsonObject(); // root keys: 0,1,2
// after
var obj = envDrivenConfig.GetSection("Settings").ToJsonObject(); Defensive patterns
Strategy: validation
Validate before calling
var children = configuration.GetChildren().ToList();
if (children.Any(c => int.TryParse(c.Key, out _))) throw new FormatException("Root configuration must have named keys, not numeric indexes."); Type guard
bool IsObjectShaped(IConfiguration c) => c.GetChildren().All(ch => !int.TryParse(ch.Key, out _));
Try / catch
try { var obj = configuration.ToJsonObject(); }
catch (FormatException ex) when (ex.Message.StartsWith("Top level JSON element")) { var node = configuration.ToJsonNode(); /* handle array root */ } Prevention
- Ensure root config keys are named, not numeric indexes
- Use GetSection() to pick object-shaped subtrees
- Inspect GetDebugView() when config shapes look wrong
When it happens
Trigger: Calling configuration.ToJsonObject() on a configuration whose root children parse as numeric keys (e.g. keys '0','1','2' from indexed sections), causing ToJsonNode to build a JsonArray at the root.
Common situations: Serializing a configuration section that stores a list under numeric keys (command-line args, environment variables like 'MyList__0'), or piping a sub-section of array-shaped data to ToJsonObject.
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
- Can't use the numeric key
- 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/bdd5e3078a60d9a0.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/Internal/ConfigurationExtensions.cs:14
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.Extensions.Configuration;
namespace OrchardCore.Environment.Shell.Configuration.Internal;
public static class ConfigurationExtensions
{
public static JsonObject ToJsonObject(this IConfiguration configuration)
{
var jsonNode = ToJsonNode(configuration);
if (jsonNode is not JsonObject jObject)
{
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.");
}View on GitHub (pinned to 4306c0717f)