{"record":{"id":"7d6fa62f6952ccc2","repo":"tonhowtf/omniget","slug":"perfil-indisponivel","errorCode":null,"errorMessage":"perfil indisponivel","messagePattern":"perfil indisponivel","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src-tauri/omniget-core/src/core/tools/x/fx.rs","lineNumber":362,"sourceCode":"    .await?;\n    let items = v\n        .get(\"replies\")\n        .and_then(|a| a.as_array())\n        .into_iter()\n        .flatten()\n        .filter_map(post_from)\n        .collect();\n    Ok(Page {\n        items,\n        cursor: bottom_cursor(&v),\n    })\n}\n\npub async fn profile(handle: &str) -> anyhow::Result<XUser> {\n    let v = get(&format!(\"profile/{}\", handle), &[]).await?;\n    v.get(\"user\")\n        .map(user_from)\n        .ok_or_else(|| anyhow!(\"perfil indisponivel\"))\n}\n\npub async fn profile_statuses(\n    handle: &str,\n    cursor: Option<&str>,\n    with_replies: bool,\n) -> anyhow::Result<Page<XPost>> {\n    let v = get(\n        &format!(\"profile/{}/statuses\", handle),\n        &[\n            (\"cursor\", cursor.unwrap_or(\"\").to_string()),\n            (\"count\", \"100\".to_string()),\n            (\n                \"with_replies\",\n                if with_replies {\n                    \"true\".to_string()\n                } else {\n                    String::new()","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/x/fx.rs#L344-L380","documentation":"profile() fetched the FxTwitter profile endpoint but the response contained no \"user\" object to convert with user_from, yielding 'perfil indisponivel'. This is a missing-field failure on a successful request, distinct from the 404/401 cases handled inside get().","triggerScenarios":"FxTwitter returns an envelope without a user field for a handle — suspended or shadow-banned account, brand-new account not yet indexed, or a schema change in FxTwitter's profile response.","commonSituations":"Requesting a recently created or suspended profile; handles with unusual casing that resolve oddly; FxTwitter degrading profile data during incidents.","solutions":["Verify the handle exists (open x.com/<handle> in a browser).","Retry — newly created accounts may appear after a delay.","Fall back to the native XClient profile fetch.","If valid profiles fail consistently, check FxTwitter's API for schema changes and update user_from."],"exampleFix":"// before\nlet v = get(&format!(\"profile/{}\", handle), &[]).await?;\nv.get(\"user\").map(user_from).ok_or_else(|| anyhow!(\"perfil indisponivel\"))\n// after\nlet v = get(&format!(\"profile/{}\", handle), &[]).await?;\nmatch v.get(\"user\").map(user_from) {\n    Some(u) => Ok(u),\n    None => xclient::profile(handle).await,\n}","handlingStrategy":"fallback","validationCode":"// regex de handle antes de chamar\nlet re = regex::Regex::new(r\"^@?[A-Za-z0-9_]{1,15}$\").unwrap();\nif !re.is_match(handle) { return Err(anyhow!(\"handle invalido: {handle}\")); }","typeGuard":"fn has_user(v: &Value) -> bool {\n    v.get(\"user\").map_or(false, |u| u.get(\"screen_name\").is_some())\n}","tryCatchPattern":"match fx::profile(&handle).await {\n    Ok(u) => u,\n    Err(e) if e.to_string().contains(\"perfil indisponivel\") => {\n        xclient::profile(&handle).await.map_err(|_| anyhow!(\"perfil {handle} indisponivel\"))?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Validate handles against ^@?[A-Za-z0-9_]{1,15}$ before calling","Treat suspended/new accounts as expected misses, not bugs","Retry once — fresh accounts can appear in FxTwitter after a delay","Fall back to the authenticated native client for authoritative profile data"],"tags":["fxtwitter","profile","missing-field","x"],"backgroundTag":"unexpected-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"}