microsoft/aspire · error · JsonException

A JSON Patch operation must contain string 'op' and 'path'…

Error message

A JSON Patch operation must contain string 'op' and 'path' properties.

What it means

JsonPatch.Apply parses each operation of a JSON Patch document and requires every operation to be a JSON object with string-valued 'op' and 'path' properties per RFC 6902. If an operation is not an object, or 'op'/'path' are missing or not strings, a JsonException is thrown to abort application of the patch.

Solutions

  1. Ensure every patch operation is a JSON object containing both "op" (string) and "path" (string).
  2. Validate the patch document against RFC 6902 before applying it.
  3. Check the producer of the patch (custom resource update code) for typos in property names.
  4. Log the raw patch JSON to identify which operation index is malformed.

Example fix

// before
[ { "operation": "replace", "path": "/spec/replicas", "value": 3 } ]
// after
[ { "op": "replace", "path": "/spec/replicas", "value": 3 } ]
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidOperation(JsonNode node) =>
    node is JsonObject o &&
    o["op"] is JsonValue ov && ov.TryGetValue<string>(out _) &&
    o["path"] is JsonValue pv && pv.TryGetValue<string>(out _);

Type guard

bool IsStringProperty(JsonObject o, string name) => o[name] is JsonValue v && v.TryGetValue<string>(out _);

Try / catch

try { patch.Apply(target); }
catch (JsonException ex)
{
    logger.LogError(ex, "Malformed JSON Patch document: {Message}", ex.Message);
}

Prevention

When it happens

Trigger: Applying a patch document whose operation lacks 'op' or 'path', or where these are non-string (e.g. "op": 1, or a shorthand form); patch JSON deserialized from an untrusted/incorrect source via ApplyUpdate on a DCP resource snapshot.

Common situations: Hand-written patch JSON with typos ('operation' instead of 'op'); producers emitting numeric op codes; schema drift between the patch producer and Aspire.Hosting's parser.

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 microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/81ca5f00d7e9c2cd. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/Dcp/JsonPatch.cs:37

        var operations = new JsonArray();
        AddOperations(current, changed, string.Empty, operations);

        return operations;
    }

    internal static JsonNode? Apply(JsonNode? current, JsonArray patch)
    {
        var result = current?.DeepClone();

        foreach (var operationNode in patch)
        {
            if (operationNode is not JsonObject operation ||
                operation["op"] is not JsonValue operationValue ||
                operation["path"] is not JsonValue pathValue ||
                !operationValue.TryGetValue<string>(out var operationName) ||
                !pathValue.TryGetValue<string>(out var path))
            {
                throw new JsonException("A JSON Patch operation must contain string 'op' and 'path' properties.");
            }

            var segments = ParsePath(path);
            var hasValue = operation.TryGetPropertyValue("value", out var value);
            result = ApplyOperation(result, operationName, segments, hasValue, value);
        }

        return result;
    }

    private static void AddOperations(JsonNode? current, JsonNode? changed, string path, JsonArray operations)
    {
        if (JsonNode.DeepEquals(current, changed))
        {
            return;
        }

        if (current is JsonObject currentObject && changed is JsonObject changedObject)

View on GitHub (pinned to 25830f84bd)