AlexxIT/go2rtc · error

xiaomi

Error message

xiaomi: %s

What it means

After decrypting the Xiaomi cloud response, Request unmarshals it and checks the application-level code field. Xiaomi APIs return code 0 on success; any other code is turned into this error with the API's message appended (e.g. 'xiaomi: invalid token'), representing a business-logic failure inside an HTTP-200 response.

Solutions

  1. Read the appended message to learn the exact API-reported cause
  2. Re-login to refresh service tokens if the message mentions token/auth
  3. Validate device DIDs and command parameters against the Xiaomi API spec
  4. Retry only for transient device-state messages (e.g. device offline) after confirming the device is online
Defensive patterns

Strategy: try-catch

Try / catch

res, err := cloud.Request(client, url, payload)
if err != nil {
    var apiErr string
    if strings.HasPrefix(err.Error(), "xiaomi: ") {
        apiErr = strings.TrimPrefix(err.Error(), "xiaomi: ")
        // route on apiErr: token issues -> re-login; device offline -> retry later
    }
    return err
}

Prevention

When it happens

Trigger: Calling xiaomi cloud Request when the API responds 200 but with a non-zero code in the decrypted payload: invalid/expired service token, device ID mismatch, unsupported command, or account permission issues.

Common situations: Tokens expired after Xiaomi session rotation; issuing commands to devices not owned by the logged-in account; device offline errors surfaced via the code/message; wrong request parameters.

Related errors


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

Appendix: source

Thrown at pkg/xiaomi/cloud.go:466

		return nil, err
	}

	plaintext, err := crypt(signedNonce, ciphertext)
	if err != nil {
		return nil, err
	}

	var res1 struct {
		Code    int             `json:"code"`
		Message string          `json:"message"`
		Result  json.RawMessage `json:"result"`
	}
	if err = json.Unmarshal(plaintext, &res1); err != nil {
		return nil, err
	}

	if res1.Code != 0 {
		return nil, errors.New("xiaomi: " + res1.Message)
	}

	return res1.Result, nil
}

func readLoginResponse(rc io.ReadCloser, v any) ([]byte, error) {
	defer rc.Close()

	body, err := io.ReadAll(rc)
	if err != nil {
		return nil, err
	}

	body, ok := bytes.CutPrefix(body, []byte("&&&START&&&"))
	if !ok {
		return nil, fmt.Errorf("xiaomi: %s", body)
	}

View on GitHub (pinned to c245815e75)