{"record":{"id":"47d293d44ebe295a","repo":"ory/hydra","slug":"unsupported-operation-s","errorCode":null,"errorMessage":"unsupported operation: %s","messagePattern":"unsupported operation: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/jsonx/patch.go","lineNumber":65,"sourceCode":"// is invalid or if the patch includes paths that are denied. denyPaths is a\n// list of path globs (interpreted with [glob.Compile] that are not allowed to\n// be patched.\nfunc ApplyJSONPatch[T any](p json.RawMessage, object T, denyPaths ...string) (result T, err error) {\n\tpatch, err := jsonpatch.DecodePatch(p)\n\tif err != nil {\n\t\treturn result, errors.WithStack(err)\n\t}\n\n\tdenyPattern := fmt.Sprintf(\"{%s}\", strings.ToLower(strings.Join(denyPaths, \",\")))\n\tmatcher, err := glob.Compile(denyPattern, '/')\n\tif err != nil {\n\t\treturn result, errors.WithStack(err)\n\t}\n\n\tfor _, op := range patch {\n\t\t// Some operations are buggy, see https://github.com/evanphx/json-patch/pull/158\n\t\tif isUnsupported(op) {\n\t\t\treturn result, errors.Errorf(\"unsupported operation: %s\", op.Kind())\n\t\t}\n\t\tpath, err := op.Path()\n\t\tif err != nil {\n\t\t\treturn result, errors.Errorf(\"error parsing patch operations: %v\", err)\n\t\t}\n\t\tif matcher.Match(strings.ToLower(path)) {\n\t\t\treturn result, errors.Errorf(\"patch includes denied path: %s\", path)\n\t\t}\n\n\t\t// JSON patch officially rejects replacing paths that don't exist, but we want to be more tolerant.\n\t\t// Therefore, we will ensure that all paths that we want to replace exist in the original document.\n\t\tif op.Kind() == \"replace\" && !isElementAccess(path) {\n\t\t\top[\"op\"] = new(json.RawMessage(`\"add\"`))\n\t\t}\n\t}\n\n\toriginal, err := json.Marshal(object)\n\tif err != nil {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/jsonx/patch.go#L47-L83","documentation":"ApplyJSONPatch in oryx/jsonx applies a JSON Patch but only allows the operations add, remove, and replace (see opAllowList). Other RFC 6902 operations — copy, move, and test — are rejected because the underlying evanphx/json-patch implementation has known bugs with them (see github.com/evanphx/json-patch/pull/158). The error names the offending operation kind.","triggerScenarios":"Calling ApplyJSONPatch with a patch document containing any operation whose \"op\" is \"copy\", \"move\", or \"test\" (anything not in {add, remove, replace}); e.g., via patchOAuth2Client receiving a user-supplied PATCH body.","commonSituations":"API clients crafting RFC 6902 patches that include 'test' preconditions or 'move'/'copy' for convenience; generic JSON Patch tooling that produces all six standard operations.","solutions":["Rewrite the patch using only add, remove, and replace: express move as remove+add, copy as read+add, and drop test preconditions.","Split the patch: perform test/copy/move client-side and send only the resulting add/remove/replace operations.","If you need copy/move server-side, apply the patch with jsonpatch directly (bypassing ApplyJSONPatch) after validating paths yourself."],"exampleFix":"// before\n[{\"op\": \"move\", \"from\": \"/a\", \"path\": \"/b\"}]\n// after\n[{\"op\": \"add\", \"path\": \"/b\", \"value\": <value of /a>}, {\"op\": \"remove\", \"path\": \"/a\"}]","handlingStrategy":"validation","validationCode":"allowed := map[string]bool{\"add\": true, \"remove\": true, \"replace\": true}\nfor _, op := range patchOps {\n    if !allowed[op[\"op\"].(string)] {\n        return fmt.Errorf(\"operation %v not allowed; use add/remove/replace\", op[\"op\"])\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Express move/copy/test as add/remove/replace before sending.","Validate patches against the RFC 6902 schema minus copy/move/test.","Document the supported operation subset for API consumers."],"tags":["json-patch","rfc6902","validation"],"backgroundTag":"unsupported-json-patch-operation","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}