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

  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.