wtfutil/wtf · error
errors.New(string(body))
Error message
errors.New(string(body))
What it means
Not a fixed message: getMonitors performs two JSON passes against the UptimeRobot API. After unmarshalling the response envelope it checks c["stat"]; UptimeRobot replies with stat="ok" on success. Anything else (stat="error") means the API rejected the request, and the widget surfaces the entire raw response body via errors.New(string(body)) so the developer can see UptimeRobot's own error description.
Source
Thrown at modules/uptimerobot/widget.go:174
)
if errh != nil {
return nil, errh
}
defer func() { _ = resp.Body.Close() }()
body, _ := io.ReadAll(resp.Body)
// First pass to read the status
c := make(map[string]json.RawMessage)
errj1 := json.Unmarshal(body, &c)
if errj1 != nil {
return nil, errj1
}
if string(c["stat"]) != `"ok"` {
return nil, errors.New(string(body))
}
// Second pass to get the actual info
var monitors []Monitor
errj2 := json.Unmarshal(c["monitors"], &monitors)
if errj2 != nil {
return nil, errj2
}
return monitors, nil
}
View on GitHub (pinned to bb838c1ccb)
Solutions
- Inspect the error text — it contains UptimeRobot's JSON error (type/message fields) explaining the cause.
- Verify the apiKey in the uptimerobot module settings is a valid, active key (use a read-only key if only monitoring).
- Check for rate limiting (message like 'exceed the calls limit') and reduce poll interval or wait.
- Confirm you are using API v2 parameters; old v1 keys/params cause error responses.
Example fix
// before: error body: {"stat":"error","error":{"type":"invalid_parameter","message":"api_key is invalid"}}
// after (settings.yml)
uptimerobot:
apiKey: "u1234567-0123456789abcdef" # valid v2 API key Defensive patterns
Strategy: validation
Validate before calling
if apiKey == "" || !strings.HasPrefix(apiKey, "u") {
return errors.New("valid UptimeRobot API v2 key required")
} Try / catch
monitors, err := getMonitors(apiKey)
if err != nil {
// err contains UptimeRobot's raw JSON body; parse it:
var apiErr struct {
Error struct{ Type, Message string } `json:"error"`
}
if json.Unmarshal([]byte(err.Error()), &apiErr) == nil {
log.Printf("uptimerobot: %s: %s", apiErr.Error.Type, apiErr.Error.Message)
}
} Prevention
- Test the API key with curl against https://api.uptimerobot.com/v2/getAccountDetails first.
- Use a read-only key when only monitoring is needed.
- Respect rate limits (10 req/min); tune poll interval accordingly.
When it happens
Trigger: Widget.Refresh -> getMonitors: the first-pass JSON decode succeeds but c["stat"] != "\"ok\"" — UptimeRobot returned an error payload such as invalid api_key, wrong monitor types parameter, or rate-limit exceeded; the whole HTTP body is embedded in the error.
Common situations: Invalid or revoked UptimeRobot API key (read-only vs full-access key mismatch); typo'd apiKey in settings.yml; exceeding UptimeRobot's API rate limits; UptimeRobot API v2 endpoint/parameter changes.
Related errors
- errors.New(response.ErrorMessage)
- unexpected status code %d from football API
- errors.New(msg.Msg)
- errors.New(hibpErr.Message)
- extracting player state failed! Please refresh or restart WT
AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03).
Data as JSON: /api/errors/351fffc9a3d45a8f.
Report an issue: GitHub.