{"record":{"id":"8d6261c83bcefc58","repo":"tonhowtf/omniget","slug":"nao-reconheci-um-perfil-do-x-em","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/media.rs","lineNumber":156,"sourceCode":"    }\n    let bytes = resp.bytes().await?;\n    let part = path.with_extension(\"part\");\n    tokio::fs::write(&part, &bytes).await?;\n    tokio::fs::rename(&part, path).await?;\n    Ok(())\n}\n\n/// Todas as midias publicas de um perfil (aba Midia), ate `limit` posts.\npub async fn download_profile(\n    input: &str,\n    dest: &str,\n    limit: usize,\n    photos: bool,\n    videos: bool,\n    progress: ProgressFn,\n) -> anyhow::Result<MediaResult> {\n    let handle = super::handle_from(input)\n        .ok_or_else(|| anyhow!(\"nao reconheci um perfil do X em: {}\", input))?;\n    let job = format!(\"x-media:{}\", handle.to_ascii_lowercase());\n    super::clear_cancel(&job);\n    let mut posts: Vec<XPost> = Vec::new();\n    let mut cursor: Option<String> = None;\n    let limit = if limit == 0 { 5000 } else { limit };\n    for _ in 0..200 {\n        if super::cancelled(&job) {\n            break;\n        }\n        super::report(&progress, &job, \"listing\", posts.len() as u64, None, None);\n        let page = super::fx::profile_media(&handle, cursor.as_deref()).await?;\n        if page.items.is_empty() {\n            break;\n        }\n        posts.extend(page.items.into_iter().filter(|p| !p.media.is_empty()));\n        if posts.len() >= limit || page.cursor.is_none() {\n            break;\n        }","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/x/media.rs#L138-L174","documentation":"download_profile parses the user input into an X handle with `handle_from` and throws this error when parsing fails. `handle_from` accepts `@name`, bare `name` (1-15 [A-Za-z0-9_]), or an x.com/twitter.com profile URL, rejecting reserved path segments like `i`, `home`, `search`. The message embeds the raw unrecognized input.","triggerScenarios":"Calling download_profile with input that is empty after trimming '@', longer than 15 chars, contains characters outside [A-Za-z0-9_], is a status URL (`/status/123`) instead of a profile URL, or a URL pointing at a reserved path (e.g. https://x.com/search?q=...).","commonSituations":"Pasting a tweet link instead of a profile link; input containing full display names with spaces (`Elon Musk`); handles with trailing punctuation from copy/paste; locale input from UI passing raw text like 'my profile'; handles longer than Twitter's 15-char limit (renamed accounts).","solutions":["Pass a valid handle: `@nasa`, `nasa`, or `https://x.com/nasa` — trim whitespace and surrounding punctuation before calling","If input may be a tweet URL, route it to thread/post functions instead, or extract the screen name via handle_from first and show a validation message on None","Reject reserved route names (i, home, search, ...) in your own UI validation before calling"],"exampleFix":"// before\ndownload_profile(user_input.trim(), 100, true, false, progress).await?;\n// after\nlet input = user_input.trim().trim_start_matches('@');\nanyhow::ensure!(!input.is_empty() && input.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') && input.len() <= 15,\n    \"'{input}' nao parece um handle do X (use @nome, nome ou https://x.com/nome)\");\ndownload_profile(input, 100, true, false, progress).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}\n// call download_profile only if is_valid_x_handle(user_input) or input is a profile URL on x.com/twitter.com","typeGuard":"fn as_x_handle(input: &str) -> Option<String> {\n    let s = input.trim().trim_start_matches('@');\n    (!s.is_empty()\n        && s.chars().count() <= 15\n        && s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_'))\n    .then(|| s.to_string())\n}","tryCatchPattern":"match download_profile(input, limit, photos, videos, progress).await {\n    Err(e) if e.to_string().contains(\"nao reconheci um perfil\") => {\n        eprintln!(\"Entrada invalida: use @handle, handle ou https://x.com/handle\");\n    }\n    Err(e) => return Err(e),\n    Ok(res) => res,\n}","preventionTips":["Trim whitespace, '@' prefix and surrounding punctuation from user input before calling","Route tweet/status URLs to post/thread functions, not profile functions","Reject reserved route names (i, home, search, explore, ...) in your own validation","Enforce X's 1-15 char [A-Za-z0-9_] handle rule in the UI before invoking the tool"],"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"}