{"record":{"id":"fe0f8dc963362462","repo":"SigNoz/signoz","slug":"dashboard-invalid-patch","errorCode":"dashboard_invalid_patch","errorMessage":"request body is not a valid RFC 6902 JSON Patch document","messagePattern":"request body is not a valid RFC 6902 JSON Patch document","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/types/dashboardtypes/perses_dashboard_patch.go","lineNumber":59,"sourceCode":"type PatchOp struct{ valuer.String }\n\nvar (\n\tPatchOpAdd     = PatchOp{valuer.NewString(\"add\")}\n\tPatchOpRemove  = PatchOp{valuer.NewString(\"remove\")}\n\tPatchOpReplace = PatchOp{valuer.NewString(\"replace\")}\n\tPatchOpMove    = PatchOp{valuer.NewString(\"move\")}\n\tPatchOpCopy    = PatchOp{valuer.NewString(\"copy\")}\n\tPatchOpTest    = PatchOp{valuer.NewString(\"test\")}\n)\n\nfunc (PatchOp) Enum() []any {\n\treturn []any{PatchOpAdd, PatchOpRemove, PatchOpReplace, PatchOpMove, PatchOpCopy, PatchOpTest}\n}\n\nfunc (p *PatchableDashboardV2) UnmarshalJSON(data []byte) error {\n\tpatch, err := jsonpatch.DecodePatch(data)\n\tif err != nil {\n\t\treturn errors.New(errors.TypeInvalidInput, ErrCodeDashboardInvalidPatch, \"request body is not a valid RFC 6902 JSON Patch document\").WithAdditional(err.Error())\n\t}\n\tif err := json.Unmarshal(data, &p.Ops); err != nil {\n\t\treturn errors.New(errors.TypeInvalidInput, ErrCodeDashboardInvalidPatch, \"request body is not a valid RFC 6902 JSON Patch document\").WithAdditional(err.Error())\n\t}\n\tp.patch = patch\n\treturn nil\n}\n\nfunc (p PatchableDashboardV2) Apply(existing *DashboardV2) (*UpdatableDashboardV2, error) {\n\texistingAsUpdatable := existing.toUpdatableDashboardV2()\n\traw, err := json.Marshal(existingAsUpdatable)\n\tif err != nil {\n\t\treturn nil, errors.WrapInternalf(err, errors.CodeInternal, \"marshal existing dashboard for patch\")\n\t}\n\tpatched, err := p.patch.ApplyWithOptions(raw, &jsonpatch.ApplyOptions{AllowMissingPathOnRemove: true, EnsurePathExistsOnAdd: true})\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, errors.TypeInvalidInput, ErrCodeDashboardInvalidPatch, \"JSON Patch could not be applied to the target dashboard\").WithAdditional(err.Error())\n\t}","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/SigNoz/signoz/blob/5069bf80b08f1f00d7e014eccc09902f9871004f/pkg/types/dashboardtypes/perses_dashboard_patch.go#L41-L77","documentation":"PatchableDashboardV2.UnmarshalJSON decodes the body both as an RFC 6902 JSON Patch (jsonpatch.DecodePatch) and as a typed Ops slice. This variant fires when DecodePatch fails: the body is not a JSON array of {op, path, value} operation objects.","triggerScenarios":"PATCH dashboard request whose body is a JSON object (full dashboard), a bare object diff, or an array with entries missing op/path.","commonSituations":"Clients sending JSON Merge Patch (RFC 7386) style bodies instead of RFC 6902; wrong Content-Type handling proxying that mangles the body; assuming REST PUT semantics for PATCH.","solutions":["Send an RFC 6902 array: [{\"op\":\"replace\",\"path\":\"/title\",\"value\":\"new\"}]","Use op values add/remove/replace/move/copy/test only","Ensure each op has a valid path (JSON Pointer starting with /)","Don't send the whole dashboard document to the PATCH endpoint"],"exampleFix":"// before\n{\"title\":\"new title\"}\n// after\n[{\"op\":\"replace\",\"path\":\"/title\",\"value\":\"new title\"}]\n","handlingStrategy":"validation","validationCode":"function isRFC6902(body: unknown): boolean {\n  return Array.isArray(body) && body.every(op => typeof op?.op === 'string' && typeof op?.path === 'string');\n}","typeGuard":"function isPatchDoc(b: unknown): b is Array<{op:string;path:string;value?:unknown}> { return isRFC6902(b); }","tryCatchPattern":null,"preventionTips":["Use a json-patch library client-side to build patches","Don't confuse merge-patch with JSON Patch"],"tags":["dashboard","json-patch","rfc-6902","validation","go"],"backgroundTag":"invalid-json-patch-document","analyzedSha":"5069bf80b08f1f00d7e014eccc09902f9871004f","analyzedAt":"2026-08-28T06:22:12.824Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}