microsoft/aspire · error · JsonException
A JSON Patch path can only traverse objects and arrays.
Error message
A JSON Patch path can only traverse objects and arrays.
What it means
JsonPatch.Apply resolves each segment of a JSON Patch path through the document tree. When an intermediate node is neither a JsonObject nor a JsonArray (e.g. a scalar like a string or number sits mid-path), the library cannot descend further and throws this JsonException. It enforces RFC 6902 semantics that a path must only traverse containers.
Solutions
- Inspect the target document at the failing path and correct the patch path so it only traverses objects/arrays
- Verify the resource's current JSON shape (e.g. via Dashboard or kubectl-style dump) before composing the path
- Split the patch into operations that create intermediate objects first (add) before descending
Example fix
// before
patch = new("replace", "/env/NAME/value", value); // 'NAME' is a string, not an object
// after
patch = new("add", "/env", new JsonObject { ["NAME"] = value }); Defensive patterns
Strategy: try-catch
Validate before calling
static bool IsPathTraversable(JsonNode root, string path) {
var current = root;
foreach (var seg in path.Split('/', StringSplitOptions.RemoveEmptyEntries)) {
if (current is JsonObject o) { if (!o.TryGetPropertyValue(seg, out current) || current is null) return false; }
else if (current is JsonArray a) { if (!int.TryParse(seg, out var i) || i < 0 || i >= a.Count) return false; current = a[i]; }
else return false; // scalar mid-path
}
return true;
} Type guard
bool IsContainer(JsonNode? node) => node is JsonObject or JsonArray;
Try / catch
try { patcher.Apply(doc, operations); }
catch (JsonException ex) when (ex.Message.Contains("can only traverse")) {
logger.LogWarning(ex, "Patch path descends into a scalar node; fix the path");
} Prevention
- Inspect the live resource JSON before composing deep patch paths
- Keep patch paths shallow; create intermediate objects with 'add' first
- Add unit tests that run patches against representative resource documents
When it happens
Trigger: Calling Apply with a patch operation whose path points through a JSON property that holds a scalar, e.g. path '/env/VALUE/more' where 'VALUE' is a string.
Common situations: Hand-written patch paths that assume deeper nesting than the DCP resource actually has; a resource schema version change that flattened a section; passing a segment that collides with a scalar property name.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- A JSON Patch path cannot traverse a null value.
- JSON Patch array index
- JSON Patch path segment
- JSON Patch path segment
- JSON Patch remove path refers to missing property
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/1f846c778b0babb1.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Dcp/JsonPatch.cs:212
{
"remove" => null,
_ => value?.DeepClone(),
};
}
var parent = GetParent(current, segments);
var finalSegment = segments[^1];
switch (parent)
{
case JsonObject jsonObject:
ApplyToObject(jsonObject, operation, finalSegment, value);
break;
case JsonArray jsonArray:
ApplyToArray(jsonArray, operation, finalSegment, value);
break;
default:
throw new JsonException("A JSON Patch path can only traverse objects and arrays.");
}
return current;
}
private static JsonNode GetParent(JsonNode? current, string[] segments)
{
var parent = current ?? throw new JsonException("A JSON Patch path cannot traverse a null value.");
for (var index = 0; index < segments.Length - 1; index++)
{
var segment = segments[index];
parent = parent switch
{
JsonObject jsonObject when jsonObject.TryGetPropertyValue(segment, out var child) && child is not null => child,
JsonArray jsonArray => jsonArray[ParseArrayIndex(segment, jsonArray.Count, allowEnd: false)]
?? throw new JsonException($"JSON Patch path segment '{segment}' refers to a null value."),
_ => throw new JsonException($"JSON Patch path segment '{segment}' does not exist."),View on GitHub (pinned to 25830f84bd)