ory/hydra · error
error parsing patch operations: %v
Error message
error parsing patch operations: %v
What it means
After allow-listing the operation kind, ApplyJSONPatch calls op.Path() on each decoded JSON Patch operation. If the operation object is malformed — most commonly a 'move' or 'copy' operation that carries 'from' but no 'path', or a non-string/missing 'path' field — evanphx/json-patch fails to extract the path and this error wraps that failure.
Source
Thrown at oryx/jsonx/patch.go:69
patch, err := jsonpatch.DecodePatch(p)
if err != nil {
return result, errors.WithStack(err)
}
denyPattern := fmt.Sprintf("{%s}", strings.ToLower(strings.Join(denyPaths, ",")))
matcher, err := glob.Compile(denyPattern, '/')
if err != nil {
return result, errors.WithStack(err)
}
for _, op := range patch {
// Some operations are buggy, see https://github.com/evanphx/json-patch/pull/158
if isUnsupported(op) {
return result, errors.Errorf("unsupported operation: %s", op.Kind())
}
path, err := op.Path()
if err != nil {
return result, errors.Errorf("error parsing patch operations: %v", err)
}
if matcher.Match(strings.ToLower(path)) {
return result, errors.Errorf("patch includes denied path: %s", path)
}
// JSON patch officially rejects replacing paths that don't exist, but we want to be more tolerant.
// Therefore, we will ensure that all paths that we want to replace exist in the original document.
if op.Kind() == "replace" && !isElementAccess(path) {
op["op"] = new(json.RawMessage(`"add"`))
}
}
original, err := json.Marshal(object)
if err != nil {
return result, errors.WithStack(err)
}
options := jsonpatch.NewApplyOptions()View on GitHub (pinned to 4174065ffb)
Solutions
- Ensure every operation in the patch document includes a string "path" member per RFC 6902.
- Validate the patch client-side with a JSON Patch schema before sending.
- Replace move/copy operations (which often lack 'path' handling here) with explicit add/remove operations.
- Check that the request body is not double-encoded: send the patch array directly, not as a JSON string.
Example fix
// before
[{"op": "remove"}]
// after
[{"op": "remove", "path": "/name"}] Defensive patterns
Strategy: validation
Validate before calling
for _, op := range patchOps {
p, ok := op["path"].(string)
if !ok || p == "" {
return fmt.Errorf("every patch operation needs a string 'path'")
}
} Prevention
- Validate the patch document with a JSON Patch schema before sending.
- Ensure the body is a JSON array, not a double-encoded string.
- Avoid move/copy ops that omit 'path'.
When it happens
Trigger: Calling ApplyJSONPatch with an operation entry missing the required "path" member or with a non-string path value, e.g. [{"op":"remove"}] or {"op":"add","path":123}. Reached via patchOAuth2Client with a hand-crafted PATCH body.
Common situations: Buggy client-side patch builders, serializers that drop empty strings, or move/copy operations that only set 'from'. Also seen when a patch is double-encoded JSON or manually assembled incorrectly.
Related errors
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/e8846c121e857e41.
Report an issue: GitHub.