SigNoz/signoz · error

ErrCodeDashboardInvalidPatch

ErrCodeDashboardInvalidPatch

Error message

JSON Patch could not be applied to the target dashboard

What it means

Apply in perses_dashboard_patch.go runs a JSON Patch (RFC 6902) against the marshaled existing dashboard using patch.ApplyWithOptions with AllowMissingPathOnRemove and EnsurePathExistsOnAdd. If the evanphx/json-patch library rejects the operation sequence (unparseable patch, invalid op, path escaping failure, mismatched types), the error is wrapped as ErrCodeDashboardInvalidPatch with the underlying patch error attached via WithAdditional.

Source

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

	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())
	}
	out := &UpdatableDashboardV2{}
	if err := json.Unmarshal(patched, out); err != nil {
		return nil, err
	}
	return out, nil
}

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Validate the patch is a legal RFC 6902 document (jsonpatch.Decode) before applying
  2. Retry with a fresh GET of the dashboard and regenerate the patch against current state
  3. Check the attached underlying error (WithAdditional) to see the exact failing op and path
  4. Fall back to a full PUT/update instead of a patch if the path churn is expected

Example fix

// before
patch := []byte(`[{"op":"replace","path":"/panels/5","value":{}}]`)
updated, err := p.Apply(existing)

// after
patch := []byte(`[{"op":"replace","path":"/panels/5/title","value":"latency"}]`)
updated, err := p.Apply(existing)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := jsonpatch.DecodePatch(patchBytes); err != nil {
    return fmt.Errorf("malformed patch: %w", err)
}
updated, err := p.Apply(existing)

Try / catch

out, err := patch.Apply(existing)
if err != nil {
    // re-fetch and regenerate patch once, then give up with a clear message
    fresh := getLatestDashboard(id)
    out, err = patch.Apply(fresh)
}

Prevention

When it happens

Trigger: Calling PatchV2 (or Apply directly) with a JSON Patch document whose ops reference paths that do not match the dashboard structure (beyond what AllowMissingPathOnRemove/EnsurePathExistsOnAdd tolerate), use an unknown op, or try to replace/add a value of the wrong type at a path (e.g. replacing an array with an object).

Common situations: Clients generating patches from a stale copy of the dashboard (concurrent edits moved/renamed fields); patch tools emitting copy/move ops with malformed from paths; UI diffing after a dashboard schema upgrade between versions.

Related errors


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