{"record":{"id":"33a5aa4a3d89bf75","repo":"tonhowtf/omniget","slug":"nao-reconheci-um-perfil-do-x-em-profile","errorCode":null,"errorMessage":"nao reconheci um perfil do X em: {}","messagePattern":"nao reconheci um perfil do X em: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/x/profile.rs","lineNumber":59,"sourceCode":"    /// Hora local (0–23).\n    pub by_hour: Vec<Slot>,\n    /// 0 = domingo.\n    pub by_weekday: Vec<Slot>,\n    pub best_hour: Option<u32>,\n    pub best_weekday: Option<u32>,\n    pub top_posts: Vec<XPost>,\n    pub top_hashtags: Vec<TagCount>,\n    pub top_mentions: Vec<TagCount>,\n    pub utc_offset_minutes: i32,\n}\n\npub async fn analyze(\n    input: &str,\n    limit: usize,\n    with_replies: bool,\n) -> anyhow::Result<ProfileReport> {\n    let handle = super::handle_from(input)\n        .ok_or_else(|| anyhow!(\"nao reconheci um perfil do X em: {}\", input))?;\n    let user = super::fx::profile(&handle).await?;\n    let mut posts: Vec<XPost> = Vec::new();\n    let mut cursor: Option<String> = None;\n    let limit = limit.clamp(20, 1000);\n    for _ in 0..40 {\n        let page = super::fx::profile_statuses(&handle, cursor.as_deref(), with_replies).await?;\n        if page.items.is_empty() {\n            break;\n        }\n        posts.extend(page.items);\n        if posts.len() >= limit || page.cursor.is_none() {\n            break;\n        }\n        cursor = page.cursor;\n        tokio::time::sleep(std::time::Duration::from_millis(250)).await;\n    }\n    posts.truncate(limit);\n    let posts = super::dedup_posts(posts);","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/x/profile.rs#L41-L77","documentation":"analyze builds a ProfileReport for an X account and throws this error when `handle_from` cannot derive a handle from the input. The parser accepts `@name`, bare alphanumeric/underscore handles up to 15 chars, and x.com/twitter.com profile URLs, rejecting reserved paths. The raw input is included in the message.","triggerScenarios":"Calling analyze with an empty string, a display name with spaces, a handle over 15 chars, a tweet/status URL instead of a profile URL, or a URL like https://x.com/i/lists/... that resolves to a reserved segment.","commonSituations":"User pastes a status permalink expecting a profile report; input collected from a search box containing free text like 'NASA official'; trailing slashes or query strings on a bare handle (`nasa?foo`); copied handle with trailing period or emoji.","solutions":["Normalize the input to one of the accepted forms (`@handle`, `handle`, `https://x.com/handle`) before calling analyze","Validate client-side with a regex like ^[A-Za-z0-9_]{1,15}$ on the trimmed, '@'-stripped input and reject early with a clear message","If the input is a tweet URL, call the thread/post tooling instead; if it's a profile URL with extra path segments (e.g. /media), strip to the first path segment"],"exampleFix":"// before\nlet report = analyze(user_text, 50, false).await?;\n// after\nlet handle = user_text.trim().trim_start_matches('@');\nif !handle.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') || handle.is_empty() || handle.len() > 15 {\n    anyhow::bail!(\"handle invalido: '{user_text}'\");\n}\nlet report = analyze(handle, 50, false).await?;","handlingStrategy":"validation","validationCode":"fn is_valid_x_handle(input: &str) -> bool {\n    let s = input.trim().trim_start_matches('@');\n    !s.is_empty() && s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') && s.chars().count() <= 15\n}\nanyhow::ensure!(is_valid_x_handle(user_input), \"use @handle, handle ou URL de perfil do X\");\nlet report = analyze(user_input, limit, with_replies).await?;","typeGuard":"fn as_x_handle(input: &str) -> Option<String> {\n    let s = input.trim().trim_start_matches('@');\n    match (s.is_empty(), s.chars().count() <= 15, s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')) {\n        (false, true, true) => Some(s.to_string()),\n        _ => None,\n    }\n}","tryCatchPattern":"match analyze(input, limit, with_replies).await {\n    Err(e) if e.to_string().contains(\"nao reconheci um perfil\") => {\n        eprintln!(\"'{}' nao e um perfil do X valido\", input);\n        Ok(ProfileReport::default())\n    }\n    Err(e) => Err(e),\n    Ok(r) => Ok(r),\n}","preventionTips":["Validate handle shape (^[A-Za-z0-9_]{1,15}$ after stripping @) before calling analyze","Detect status URLs early and redirect them to thread analysis instead","Strip query strings/trailing slashes when constructing profile URLs yourself","Show the accepted input formats in UI tooltips to reduce free-text input"],"tags":["validation","input-parsing","url","x"],"backgroundTag":"invalid-argument-format","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}