{"record":{"id":"fc3806639dedb9ae","repo":"tonhowtf/omniget","slug":"o-device-flow-precisa-do-client-secret-da-sua-app-do-trakt","errorCode":null,"errorMessage":"o device flow precisa do client_secret da sua app do Trakt","messagePattern":"o device flow precisa do client_secret da sua app do Trakt","errorType":"validation","errorClass":"anyhow","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/lists/trakt.rs","lineNumber":297,"sourceCode":"    })\n}\n\n#[derive(Debug, Clone, Serialize)]\npub struct ConnectResult {\n    pub connected: bool,\n    pub username: String,\n    pub message: String,\n}\n\n/// Passo 2: consulta até o usuário liberar (ou o código morrer). Respeita o\n/// intervalo pedido e recua quando leva 429.\npub async fn wait_for_token(dc: &DeviceCode, p: ProgressFn) -> Result<ConnectResult> {\n    let c = {\n        let _g = LOCK.lock().unwrap_or_else(|e| e.into_inner());\n        load()\n    };\n    if c.client_secret.is_empty() {\n        return Err(anyhow!(\n            \"o device flow precisa do client_secret da sua app do Trakt\"\n        ));\n    }\n    let http = client()?;\n    let started = Instant::now();\n    let deadline = Duration::from_secs(dc.expires_in.clamp(60, 1800));\n    let mut interval = Duration::from_secs(dc.interval);\n    loop {\n        if started.elapsed() >= deadline {\n            return Err(anyhow!(\"{}\", Poll::Expired.message()));\n        }\n        tokio::time::sleep(interval).await;\n        let left = deadline.saturating_sub(started.elapsed()).as_secs();\n        report(\n            &p,\n            TOOL_ID,\n            \"progress\",\n            started.elapsed().as_secs(),","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/lists/trakt.rs#L279-L315","documentation":"Thrown by wait_for_token when the stored config has no client_secret. Trakt's device-flow token exchange (/oauth/device/token) requires client_secret alongside device_code, so polling cannot proceed without it.","triggerScenarios":"Calling wait_for_token() with a config whose client_secret field is empty — the app only registered client_id, or the secret was cleared by a config reset.","commonSituations":"User pasted only the client_id during setup; secret field lost after editing/migrating the config; app was recreated on Trakt and the old secret no longer exists.","solutions":["Copy the client_secret from the app page at https://trakt.tv/oauth/applications","Save it into the Trakt config store before calling wait_for_token()","Re-run the device flow (device_code + wait_for_token) once both credentials are stored"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if config.client_secret.trim().is_empty() {\n    return Err(\"configure o client_secret do Trakt antes de conectar\".into());\n}","typeGuard":"fn has_client_secret(c: &TraktConfig) -> bool { !c.client_secret.trim().is_empty() }","tryCatchPattern":null,"preventionTips":["Collect both client_id and client_secret in one setup step","Validate credential completeness before starting wait_for_token","Back up the config before resets/migrations"],"tags":["oauth","trakt","config","device-flow"],"backgroundTag":"missing-credentials","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}