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

  1. Remove or rename one of the duplicated keys so each path is unique
  2. Search the JSON for repeated property names differing only by case
  3. If merging documents, merge objects key-by-key instead of concatenating properties
  4. 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

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


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)