OrchardCMS/OrchardCore · error · FormatException
A duplicate key ' ' was found.
Error message
A duplicate key '{key}' was found. What it means
While flattening the JSON document, VisitValue stores each scalar under the current property path. Because the internal dictionary is case-insensitive, encountering the same effective path twice (e.g. 'Foo' and 'foo' as sibling keys, or a key appearing at the same nested path) raises FormatException 'A duplicate key was found.' Configuration keys must be unique per path.
Solutions
- Remove or rename one of the duplicated keys so each path is unique
- Search the JSON for repeated property names differing only by case
- If merging documents, merge objects key-by-key instead of concatenating properties
- Validate uniqueness (case-insensitive) before parsing
Example fix
// before
{"ConnectionStrings": {"Default": "a"}, "connectionstrings": {"default": "b"}}
// after
{"ConnectionStrings": {"Default": "b"}} Defensive patterns
Strategy: validation
Validate before calling
using var doc = JsonDocument.Parse(document, JOptions.Document);
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
void Walk(JsonElement e, string path)
{
if (e.ValueKind != JsonValueKind.Object) return;
foreach (var p in e.EnumerateObject())
{
var key = path + ":" + p.Name;
if (!seen.Add(key)) throw new InvalidDataException($"Duplicate key '{key}'");
Walk(p.Value, key);
}
}
Walk(doc.RootElement, ""); Try / catch
try { JsonConfigurationParser.Parse(document); }
catch (FormatException ex) when (ex.Message.StartsWith("A duplicate key"))
{ log.LogError(ex, "Remove duplicated property in config JSON"); } Prevention
- Never merge JSON objects by concatenating properties
- Detect duplicate keys with a case-insensitive pre-parse check
- Search for sibling properties differing only by case
- Keep one canonical source for each settings section
When it happens
Trigger: Calling JsonConfigurationParser.Parse/ParseAsync with a document containing two properties that normalize to the same path, like {"Key": "a", "key": "b"} or duplicated keys after case-insensitive comparison in nested objects.
Common situations: Merged appsettings where an object was accidentally duplicated at the same level; hand-merged JSON that kept both old and new copies of a section; code generators emitting the same property twice with different casing.
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 numeric key
- Can't use the non numeric key
- Top-level JSON element must be an object. Instead
- Could not parse the JSON document.
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/61c59b0f8b597e74.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Abstractions/Shell/Configuration/Internal/JsonConfigurationParser.cs:160
break;
case JsonValueKind.Number:
case JsonValueKind.String:
case JsonValueKind.True:
case JsonValueKind.False:
case JsonValueKind.Null:
// Skipping null values is useful to override array items,
// it allows to keep non null items at the right position.
if (visitArray && value.ValueKind == JsonValueKind.Null)
{
break;
}
var key = _paths.Peek();
if (_data.ContainsKey(key))
{
throw new FormatException($"A duplicate key '{key}' was found.");
}
_data[key] = value.ToString();
break;
default:
throw new FormatException($"Unsupported JSON token '{value.ValueKind}' was found.");
}
}
private void EnterContext(string context) =>
_paths.Push(_paths.Count > 0 ?
_paths.Peek() + ConfigurationPath.KeyDelimiter + context :
context);
private void ExitContext() => _paths.Pop();
}
View on GitHub (pinned to 4306c0717f)