AlexxIT/go2rtc · error

tuya:

Error message

tuya: 

What it means

getLoginToken's guard on the Tuya cloud login response: the HTTP request and JSON decode succeeded, but the response body reports Success=false, and the server-provided Msg is appended after the 'tuya: ' prefix. The cause is server-side rejection of the login attempt — bad credentials, wrong app credentials, or an account issue described by Msg.

Solutions

  1. Verify tuya client ID and secret are correct and active in the Tuya IoT platform
  2. Confirm the server host/region matches where the account is registered
  3. Check the returned Msg text (after the "tuya: " prefix) for the exact vendor reason
  4. Ensure system clock is accurate since Tuya request signing is time-sensitive
Defensive patterns

Strategy: try-catch

Try / catch

token, err := getLoginToken(client, host, id, secret)
if err != nil {
	var apiErr string
	if strings.HasPrefix(err.Error(), "tuya: ") {
		apiErr = strings.TrimPrefix(err.Error(), "tuya: ")
	}
	log.Printf("tuya token exchange failed: %s", apiErr)
}

Prevention

When it happens

Trigger: The POST to the Tuya token endpoint returns success=false — invalid/missing access credentials (client key/secret), wrong region server host, or expired/revoked Tuya developer credentials.

Common situations: Misconfigured tuya_client_id/tuya_client_secret; using an endpoint for a different data center; Tuya developer account suspended; clock skew invalidating the signed request on the vendor side.

Related errors


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

Appendix: source

Thrown at internal/tuya/tuya.go:204

	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	req.Header.Set("Accept", "*/*")
	req.Header.Set("Origin", fmt.Sprintf("https://%s", serverHost))
	req.Header.Set("Referer", fmt.Sprintf("https://%s/login", serverHost))
	req.Header.Set("X-Requested-With", "XMLHttpRequest")

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var tokenResp tuya.LoginTokenResponse
	if err = json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
		return nil, err
	}

	if !tokenResp.Success {
		return nil, errors.New("tuya: " + tokenResp.Msg)
	}

	return &tokenResp, nil
}

func performLogin(client *http.Client, url string, loginReq tuya.PasswordLoginRequest, serverHost string) (*tuya.PasswordLoginResponse, error) {
	jsonData, err := json.Marshal(loginReq)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}

	req.Header.Set("Content-Type", "application/json; charset=utf-8")
	req.Header.Set("Accept", "*/*")

View on GitHub (pinned to c245815e75)