SigNoz/signoz · error

ErrCodeDashboardInvalidData

ErrCodeDashboardInvalidData

Error message

invalid dashboard data

What it means

GetWidgetQuery serializes dashboard.Data to JSON and then unmarshals it into an internal dashboardData struct. This first failure means dashboard.Data itself cannot be marshalled to JSON — almost always because Data holds a value with an unsupported type (chan, func, complex number, cyclic reference) or a custom MarshalJSON that errors.

Source

Thrown at pkg/types/dashboardtypes/dashboard.go:349

		Widgets []struct {
			PanelTypes string `json:"panelTypes"`
			Query      struct {
				Builder struct {
					QueryData          []map[string]any `json:"queryData"`
					QueryFormulas      []map[string]any `json:"queryFormulas"`
					QueryTraceOperator []map[string]any `json:"queryTraceOperator"`
				} `json:"builder"`
				ClickhouseSQL []map[string]any `json:"clickhouse_sql"`
				PromQL        []map[string]any `json:"promql"`
				QueryType     string           `json:"queryType"`
			} `json:"query"`
			FillGaps bool `json:"fillSpans"`
		} `json:"widgets"`
	}

	dataJSON, err := json.Marshal(dashboard.Data)
	if err != nil {
		return nil, errors.Wrapf(err, errors.TypeInvalidInput, ErrCodeDashboardInvalidData, "invalid dashboard data")
	}

	var data dashboardData
	err = json.Unmarshal(dataJSON, &data)
	if err != nil {
		return nil, errors.Wrapf(err, errors.TypeInvalidInput, ErrCodeDashboardInvalidData, "invalid dashboard data")
	}

	if int(widgetIndex) >= len(data.Widgets) {
		return nil, errors.Newf(errors.TypeInvalidInput, ErrCodeDashboardInvalidInput, "widget with index %v doesn't exist", widgetIndex)
	}

	compositeQueries := []any{}
	widgetData := data.Widgets[widgetIndex]
	switch widgetData.Query.QueryType {
	case "builder":
		for _, query := range widgetData.Query.Builder.QueryData {
			queryName, ok := query["queryName"].(string)

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Ensure dashboard.Data contains only JSON-serializable values (maps, slices, strings, numbers, bools)
  2. If using custom types, implement error-free json.Marshaler on them
  3. Construct dashboards by decoding from JSON so Data is inherently plain

Example fix

// before
dashboard.Data = map[string]any{"ch": make(chan int)}

// after
dashboard.Data = map[string]any{"widgets": []any{}}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := json.Marshal(dashboard.Data); err != nil {
    return fmt.Errorf("dashboard.Data not serializable: %w", err)
}

Type guard

func dataIsJSONSafe(v any) bool {
    enc := json.NewEncoder(io.Discard)
    enc.SetDiscard() // or use Marshal
    _, err := json.Marshal(v)
    return err == nil
}

Try / catch

q, err := d.GetWidgetQuery(idx, ...)
if err != nil && strings.Contains(err.Error(), "invalid dashboard data") {
    return errors.New("dashboard data is not valid JSON-compatible; re-save the dashboard in the UI")
}

Prevention

When it happens

Trigger: Calling GetWidgetQuery (via GetPublicWidgetQueryRange) on a dashboard whose Data field contains unserializable values or a nested type whose MarshalJSON returns an error.

Common situations: Programmatically constructed Dashboard objects (not decoded from JSON) holding Go-native non-serializable fields; custom data types injected into Data by integrations; cyclic structs from builder patterns.

Related errors


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