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.

Solutions

  1. Inspect the error text — it contains UptimeRobot's JSON error (type/message fields) explaining the cause.
  2. Verify the apiKey in the uptimerobot module settings is a valid, active key (use a read-only key if only monitoring).
  3. Check for rate limiting (message like 'exceed the calls limit') and reduce poll interval or wait.
  4. 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

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


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

Appendix: 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)