AlexxIT/go2rtc · error

%d: %s

Error message

%d: %s

What it means

GetBaseURL calls the Roborock API and decodes a JSON envelope containing Code and Msg fields. When the server responds with a code other than 200, the function returns an error formatted as "<code>: <msg>". This is the library's way of surfacing Roborock API-level errors (auth failures, bad requests, rate limits) carried inside an otherwise successful HTTP response.

Solutions

  1. Read the numeric code and Msg in the error to identify the API failure (e.g. auth vs server error).
  2. Verify username/password or refresh the auth token, then retry.
  3. Use the correct regional base URL for your Roborock account (EU/US/CN etc.).
  4. Retry after a delay if the code indicates rate limiting or a transient server error.
Defensive patterns

Strategy: try-catch

Validate before calling

if baseURL == "" || username == "" || password == "" {
    return errors.New("baseURL, username and password are required")
}

Try / catch

url, err := roborock.GetBaseURL(client)
if err != nil {
    var apiErr *roborock.APIError // or parse "<code>: <msg>"
    // log code and message, decide whether to retry (5xx/throttle) or fail (auth)
    return err
}

Prevention

When it happens

Trigger: Calling GetBaseURL when the Roborock server rejects the request: invalid credentials, expired token, wrong endpoint region, or server-side error — any response whose JSON body has Code != 200.

Common situations: Wrong regional base URL for your account; expired login session; Roborock service outage or rate limiting; passing malformed credentials.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/8f06a9ca5ac6e7df. Report an issue: GitHub.

Appendix: source

Thrown at pkg/roborock/api.go:54

		return "", err
	}

	client := http.Client{Timeout: time.Second * 5000}
	res, err := client.Do(req)

	var v struct {
		Msg  string `json:"msg"`
		Code int    `json:"code"`
		Data struct {
			URL string `json:"url"`
		} `json:"data"`
	}
	if err = json.NewDecoder(res.Body).Decode(&v); err != nil {
		return "", err
	}

	if v.Code != 200 {
		return "", fmt.Errorf("%d: %s", v.Code, v.Msg)
	}

	return v.Data.URL, nil
}

func Login(baseURL, username, password string) (*UserInfo, error) {
	u := baseURL + "/api/v1/login?username=" + url.QueryEscape(username) +
		"&password=" + url.QueryEscape(password) + "&needtwostepauth=false"
	req, err := http.NewRequest("POST", u, nil)
	if err != nil {
		return nil, err
	}

	clientID := core.RandString(16, 64)
	clientID = base64.StdEncoding.EncodeToString([]byte(clientID))
	req.Header.Set("header_clientid", clientID)

	client := http.Client{Timeout: time.Second * 5000}

View on GitHub (pinned to c245815e75)