{"record":{"id":"422fce1acde34dad","repo":"tonhowtf/omniget","slug":"o-trakt-n-o-devolveu-o-c-digo-do-dispositivo","errorCode":null,"errorMessage":"o Trakt não devolveu o código do dispositivo","messagePattern":"o Trakt não devolveu o código do dispositivo","errorType":"exception","errorClass":"anyhow","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/lists/trakt.rs","lineNumber":266,"sourceCode":"            r.status()\n        ));\n    }\n    let v: Value = r.json().await?;\n    parse_device_code(&v)\n}\n\npub fn parse_device_code(v: &Value) -> Result<DeviceCode> {\n    let s = |k: &str| {\n        v.get(k)\n            .and_then(|x| x.as_str())\n            .unwrap_or_default()\n            .to_string()\n    };\n    let n = |k: &str, d: u64| v.get(k).and_then(|x| x.as_u64()).unwrap_or(d);\n    let device = s(\"device_code\");\n    let user = s(\"user_code\");\n    if device.is_empty() || user.is_empty() {\n        return Err(anyhow!(\"o Trakt não devolveu o código do dispositivo\"));\n    }\n    let mut url = s(\"verification_url\");\n    if url.is_empty() {\n        url = \"https://trakt.tv/activate\".to_string();\n    }\n    Ok(DeviceCode {\n        device_code: device,\n        user_code: user,\n        verification_url: url,\n        expires_in: n(\"expires_in\", 600),\n        // O Trakt pede 5 s; menos que isso leva 429.\n        interval: n(\"interval\", 5).clamp(1, 60),\n    })\n}\n\n#[derive(Debug, Clone, Serialize)]\npub struct ConnectResult {\n    pub connected: bool,","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/lists/trakt.rs#L248-L284","documentation":"Thrown by parse_device_code when the JSON returned by Trakt's device/code endpoint lacks a non-empty device_code or user_code field. These two values are mandatory to drive the device flow (polling token + code the user enters), so their absence makes the response unusable.","triggerScenarios":"Trakt returned a success status but the body is missing device_code or user_code — e.g. an unexpected JSON shape, an error object with 200 semantics, or an empty/error body parsed as JSON.","commonSituations":"API changes on Trakt's side, a proxy/captive portal returning HTML or JSON without the fields, mocking/testing with incomplete fixtures (note the test codigo_do_dispositivo_tem_padrao_quando_falta_campo covers optional-field defaults, but device/user codes remain mandatory).","solutions":["Log the raw response body from /oauth/device/code and inspect its shape","Verify the request hit the real Trakt API (no proxy/interceptor altering the body)","Retry the request — transient gateway responses can masquerade as success","If Trakt changed the field names, update parse_device_code accordingly"],"exampleFix":"// before\nlet v: Value = r.json().await?;\nparse_device_code(&v)\n// after\nlet v: Value = r.json().await?;\nif v.get(\"device_code\").is_none() {\n    tracing::error!(\"unexpected device/code body: {}\", v);\n}\nparse_device_code(&v)","handlingStrategy":"try-catch","validationCode":"let body = resp.text().await?;\nlet v: serde_json::Value = serde_json::from_str(&body)?;\nif v.get(\"device_code\").and_then(|x| x.as_str()).map_or(true, str::is_empty) {\n    // log body and abort before parsing into DeviceCode\n}","typeGuard":"fn has_device_code(v: &serde_json::Value) -> bool {\n    v.get(\"device_code\").and_then(|x| x.as_str()).map_or(false, |s| !s.is_empty())\n}","tryCatchPattern":"match device_code().await {\n    Err(e) if e.to_string().contains(\"não devolveu o código\") => {\n        tracing::error!(\"unexpected Trakt device/code response\");\n    }\n    other => other?,\n}","preventionTips":["Log raw API bodies when shapes deviate","Test parse_device_code against realistic Trakt fixtures","Watch for Trakt API changelog updates"],"tags":["oauth","trakt","json","device-flow"],"backgroundTag":"unexpected-api-response-shape","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"}