wtfutil/wtf · error

errors.New(msg.Msg)

Error message

errors.New(msg.Msg)

What it means

grafana client.Alerts() parses the API response; when Grafana returns a non-OK status the body is decoded for its 'message' field and that message is surfaced as a Go error via errors.New(msg.Msg). The text you see is Grafana's own API error message passed through verbatim (it may be empty if the body lacks 'message').

Source

Thrown at modules/grafana/client.go:103

	if client.apiKey != "" {
		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", client.apiKey))
	}

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer func() { _ = res.Body.Close() }()

	if res.StatusCode != 200 {
		msg := struct {
			Msg string `json:"message"`
		}{}
		err = utils.ParseJSON(&msg, res.Body)
		if err != nil {
			return nil, err
		}
		return nil, errors.New(msg.Msg)
	}

	var out []Alert
	err = utils.ParseJSON(&out, res.Body)
	if err != nil {
		return nil, err
	}

	sort.SliceStable(out, func(i, j int) bool {
		return out[i].State < out[j].State
	})

	return out, nil
}

View on GitHub (pinned to bb838c1ccb)

Solutions

  1. Verify the Grafana API key (Viewer+ role, correct org) and apiURL in the widget config
  2. Confirm your Grafana version's alerting API path and update the module or Grafana to a compatible version
  3. Test the endpoint manually: curl -H 'Authorization: Bearer <key>' <apiURL>/api/alerts
  4. Check the returned message text — it names the specific auth/permission/path problem

Example fix

# before
curl -H "Authorization: Bearer expiredkey" https://grafana/api/alerts  -> 401 invalid API key
# after
curl -H "Authorization: Bearer <valid service-account token>" https://grafana/api/alerts
Defensive patterns

Strategy: try-catch

Validate before calling

// verify API access before widget refresh
resp, _ := http.Get(apiURL + "/api/health")
if resp == nil || resp.StatusCode != 200 {
    return errors.New("grafana unreachable or wrong apiURL")
}

Try / catch

alerts, err := client.Alerts()
if err != nil {
    var apiErr *grafanaAPIError
    if errors.As(err, &apiErr) {
        log.Printf("grafana said: %s", apiErr.Msg) // pass-through message
    }
    return err
}

Prevention

When it happens

Trigger: Grafana API returning 401/403 (bad or missing API key), 404 (wrong path/apiURL or alert endpoints disabled), 4xx/5xx from a proxy; /api/alerts endpoint unavailable in newer Grafana versions (unified alerting moved to /api/v1/provisioning or /api/alertmanager).

Common situations: Grafana v9+ where legacy /api/alerts returns an error for unified alerting users; expired API key; reversed-proxy auth wall returning an HTML error page; wrong org/API key without alert read permissions.

Related errors


AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03). Data as JSON: /api/errors/4032d614aa53d3e0. Report an issue: GitHub.