SigNoz/signoz · error

dashboard_invalid_patch

dashboard_invalid_patch

Error message

request body is not a valid RFC 6902 JSON Patch document

What it means

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.

Source

Thrown at pkg/types/dashboardtypes/perses_dashboard_patch.go:59

type PatchOp struct{ valuer.String }

var (
	PatchOpAdd     = PatchOp{valuer.NewString("add")}
	PatchOpRemove  = PatchOp{valuer.NewString("remove")}
	PatchOpReplace = PatchOp{valuer.NewString("replace")}
	PatchOpMove    = PatchOp{valuer.NewString("move")}
	PatchOpCopy    = PatchOp{valuer.NewString("copy")}
	PatchOpTest    = PatchOp{valuer.NewString("test")}
)

func (PatchOp) Enum() []any {
	return []any{PatchOpAdd, PatchOpRemove, PatchOpReplace, PatchOpMove, PatchOpCopy, PatchOpTest}
}

func (p *PatchableDashboardV2) UnmarshalJSON(data []byte) error {
	patch, err := jsonpatch.DecodePatch(data)
	if err != nil {
		return errors.New(errors.TypeInvalidInput, ErrCodeDashboardInvalidPatch, "request body is not a valid RFC 6902 JSON Patch document").WithAdditional(err.Error())
	}
	if err := json.Unmarshal(data, &p.Ops); err != nil {
		return errors.New(errors.TypeInvalidInput, ErrCodeDashboardInvalidPatch, "request body is not a valid RFC 6902 JSON Patch document").WithAdditional(err.Error())
	}
	p.patch = patch
	return nil
}

func (p PatchableDashboardV2) Apply(existing *DashboardV2) (*UpdatableDashboardV2, error) {
	existingAsUpdatable := existing.toUpdatableDashboardV2()
	raw, err := json.Marshal(existingAsUpdatable)
	if err != nil {
		return nil, errors.WrapInternalf(err, errors.CodeInternal, "marshal existing dashboard for patch")
	}
	patched, err := p.patch.ApplyWithOptions(raw, &jsonpatch.ApplyOptions{AllowMissingPathOnRemove: true, EnsurePathExistsOnAdd: true})
	if err != nil {
		return nil, errors.Wrap(err, errors.TypeInvalidInput, ErrCodeDashboardInvalidPatch, "JSON Patch could not be applied to the target dashboard").WithAdditional(err.Error())
	}

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Send an RFC 6902 array: [{"op":"replace","path":"/title","value":"new"}]
  2. Use op values add/remove/replace/move/copy/test only
  3. Ensure each op has a valid path (JSON Pointer starting with /)
  4. Don't send the whole dashboard document to the PATCH endpoint

Example fix

// before
{"title":"new title"}
// after
[{"op":"replace","path":"/title","value":"new title"}]
Defensive patterns

Strategy: validation

Validate before calling

function isRFC6902(body: unknown): boolean {
  return Array.isArray(body) && body.every(op => typeof op?.op === 'string' && typeof op?.path === 'string');
}

Type guard

function isPatchDoc(b: unknown): b is Array<{op:string;path:string;value?:unknown}> { return isRFC6902(b); }

Prevention

When it happens

Trigger: PATCH dashboard request whose body is a JSON object (full dashboard), a bare object diff, or an array with entries missing op/path.

Common situations: 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.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/fe0f8dc963362462. Report an issue: GitHub.