{"record":{"id":"734fd77c79ae3544","repo":"AlexxIT/go2rtc","slug":"tuya-w","errorCode":null,"errorMessage":"tuya: %w","messagePattern":"tuya: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tuya/client.go","lineNumber":91,"sourceCode":"\n\tuseSmartApi := deviceId != \"\" && email != \"\" && password != \"\"\n\tuseCloudApi := deviceId != \"\" && uid != \"\" && clientId != \"\" && clientSecret != \"\"\n\n\tif streamResolution == \"\" || (streamResolution != \"hd\" && streamResolution != \"sd\") {\n\t\tstreamResolution = \"hd\"\n\t}\n\n\tif !useSmartApi && !useCloudApi {\n\t\treturn nil, errors.New(\"tuya: wrong query params\")\n\t}\n\n\tclient := &Client{\n\t\thandlers: make(map[uint32]func(*rtp.Packet)),\n\t}\n\n\tif useSmartApi {\n\t\tif client.api, err = NewTuyaSmartApiClient(nil, u.Hostname(), email, password, deviceId); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"tuya: %w\", err)\n\t\t}\n\t} else {\n\t\tif client.api, err = NewTuyaCloudApiClient(u.Hostname(), uid, deviceId, clientId, clientSecret); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"tuya: %w\", err)\n\t\t}\n\t}\n\n\tif err := client.api.Init(); err != nil {\n\t\treturn nil, fmt.Errorf(\"tuya: %w\", err)\n\t}\n\n\tclient.streamType = client.api.GetStreamType(streamResolution)\n\tclient.isHEVC = client.api.IsHEVC(client.streamType)\n\n\t// Create a new PeerConnection\n\tconf := pion.Configuration{\n\t\tICEServers:         client.api.GetICEServers(),\n\t\tICETransportPolicy: pion.ICETransportPolicyAll,","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/tuya/client.go#L73-L109","documentation":"Client.Dial wraps failures from constructing the Tuya cloud API client (smart API or cloud API) with the \"tuya: \" prefix. It means authentication or initialization against the Tuya cloud backend failed before any streaming could start.","triggerScenarios":"Dial with useSmartApi=true and NewTuyaSmartApiClient failing (bad email/password, unreachable host, missing region), or with cloud credentials (uid/clientId/clientSecret/deviceId) rejected by NewTuyaCloudApiClient.","commonSituations":"Expired or wrong Tuya account credentials; wrong region hostname; revoked or mistyped clientSecret; device removed from the account; Tuya cloud outage or rate limiting.","solutions":["Check the wrapped error (errors.Unwrap) for the precise cloud failure (401 vs DNS vs 4xx)","Re-enter/refresh Tuya account credentials and confirm the device is still bound to the account","Verify the region hostname and API keys (clientId/clientSecret) are correct for your Tuya project","Test the Tuya cloud API separately (curl) to rule out cloud-side outages"],"exampleFix":"// before\nclient, err := tuya.Dial(u, tuya.WithSmartApi(email, password))\n// after\nclient, err := tuya.Dial(u, tuya.WithSmartApi(email, password))\nif err != nil {\n\tvar apiErr *tuya.APIError\n\tif errors.As(err, &apiErr) && apiErr.Code == 401 {\n\t\t// refresh credentials / re-login before retrying\n\t}\n\treturn err\n}","handlingStrategy":"try-catch","validationCode":"if email == \"\" || password == \"\" || deviceId == \"\" {\n\treturn fmt.Errorf(\"missing tuya credentials or deviceId\")\n}","typeGuard":null,"tryCatchPattern":"client, err := tuya.Dial(u, opts...)\nif err != nil {\n\tvar inner error\n\tif errors.As(err, &inner) {\n\t\t// inner is the raw Tuya cloud error: 401 => refresh creds\n\t}\n\treturn err\n}","preventionTips":["Validate credentials and deviceId before dialing","Confirm device is still bound to the Tuya account","Keep API keys (clientId/secret) and region in config, verified at startup","Handle 401/403 from Tuya by refreshing credentials and retrying once"],"tags":["tuya","cloud","authentication","api"],"backgroundTag":"api-error-response","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}