tonhowtf/omniget · error

nao reconheci um perfil do X em

Error message

nao reconheci um perfil do X em: {}

What it means

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.

Solutions

  1. Pass a valid handle: `@nasa`, `nasa`, or `https://x.com/nasa` — trim whitespace and surrounding punctuation before calling
  2. 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
  3. Reject reserved route names (i, home, search, ...) in your own UI validation before calling

Example fix

// before
download_profile(user_input.trim(), 100, true, false, progress).await?;
// after
let input = user_input.trim().trim_start_matches('@');
anyhow::ensure!(!input.is_empty() && input.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') && input.len() <= 15,
    "'{input}' nao parece um handle do X (use @nome, nome ou https://x.com/nome)");
download_profile(input, 100, true, false, progress).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_x_handle(input: &str) -> bool {
    let s = input.trim().trim_start_matches('@');
    !s.is_empty() && s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') && s.chars().count() <= 15
}
// call download_profile only if is_valid_x_handle(user_input) or input is a profile URL on x.com/twitter.com

Type guard

fn as_x_handle(input: &str) -> Option<String> {
    let s = input.trim().trim_start_matches('@');
    (!s.is_empty()
        && s.chars().count() <= 15
        && s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_'))
    .then(|| s.to_string())
}

Try / catch

match download_profile(input, limit, photos, videos, progress).await {
    Err(e) if e.to_string().contains("nao reconheci um perfil") => {
        eprintln!("Entrada invalida: use @handle, handle ou https://x.com/handle");
    }
    Err(e) => return Err(e),
    Ok(res) => res,
}

Prevention

When it happens

Trigger: 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=...).

Common situations: 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).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/8d6261c83bcefc58. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/x/media.rs:156

    }
    let bytes = resp.bytes().await?;
    let part = path.with_extension("part");
    tokio::fs::write(&part, &bytes).await?;
    tokio::fs::rename(&part, path).await?;
    Ok(())
}

/// Todas as midias publicas de um perfil (aba Midia), ate `limit` posts.
pub async fn download_profile(
    input: &str,
    dest: &str,
    limit: usize,
    photos: bool,
    videos: bool,
    progress: ProgressFn,
) -> anyhow::Result<MediaResult> {
    let handle = super::handle_from(input)
        .ok_or_else(|| anyhow!("nao reconheci um perfil do X em: {}", input))?;
    let job = format!("x-media:{}", handle.to_ascii_lowercase());
    super::clear_cancel(&job);
    let mut posts: Vec<XPost> = Vec::new();
    let mut cursor: Option<String> = None;
    let limit = if limit == 0 { 5000 } else { limit };
    for _ in 0..200 {
        if super::cancelled(&job) {
            break;
        }
        super::report(&progress, &job, "listing", posts.len() as u64, None, None);
        let page = super::fx::profile_media(&handle, cursor.as_deref()).await?;
        if page.items.is_empty() {
            break;
        }
        posts.extend(page.items.into_iter().filter(|p| !p.media.is_empty()));
        if posts.len() >= limit || page.cursor.is_none() {
            break;
        }

View on GitHub (pinned to 8600b91f42)