tonhowtf/omniget · error
nao reconheci um perfil do X em
Error message
nao reconheci um perfil do X em: {} What it means
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.
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
Example fix
// before
let report = analyze(user_text, 50, false).await?;
// after
let handle = user_text.trim().trim_start_matches('@');
if !handle.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') || handle.is_empty() || handle.len() > 15 {
anyhow::bail!("handle invalido: '{user_text}'");
}
let report = analyze(handle, 50, false).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
}
anyhow::ensure!(is_valid_x_handle(user_input), "use @handle, handle ou URL de perfil do X");
let report = analyze(user_input, limit, with_replies).await?; Type guard
fn as_x_handle(input: &str) -> Option<String> {
let s = input.trim().trim_start_matches('@');
match (s.is_empty(), s.chars().count() <= 15, s.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')) {
(false, true, true) => Some(s.to_string()),
_ => None,
}
} Try / catch
match analyze(input, limit, with_replies).await {
Err(e) if e.to_string().contains("nao reconheci um perfil") => {
eprintln!("'{}' nao e um perfil do X valido", input);
Ok(ProfileReport::default())
}
Err(e) => Err(e),
Ok(r) => Ok(r),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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
- nao reconheci um perfil do X em
- nao reconheci um post do X em
- a API oficial so aceita URLs publicas (https://…) para os…
- cole a URL de um .m3u8 ou .mpd
- cole um link do slideshare.net
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/33a5aa4a3d89bf75.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/x/profile.rs:59
/// Hora local (0–23).
pub by_hour: Vec<Slot>,
/// 0 = domingo.
pub by_weekday: Vec<Slot>,
pub best_hour: Option<u32>,
pub best_weekday: Option<u32>,
pub top_posts: Vec<XPost>,
pub top_hashtags: Vec<TagCount>,
pub top_mentions: Vec<TagCount>,
pub utc_offset_minutes: i32,
}
pub async fn analyze(
input: &str,
limit: usize,
with_replies: bool,
) -> anyhow::Result<ProfileReport> {
let handle = super::handle_from(input)
.ok_or_else(|| anyhow!("nao reconheci um perfil do X em: {}", input))?;
let user = super::fx::profile(&handle).await?;
let mut posts: Vec<XPost> = Vec::new();
let mut cursor: Option<String> = None;
let limit = limit.clamp(20, 1000);
for _ in 0..40 {
let page = super::fx::profile_statuses(&handle, cursor.as_deref(), with_replies).await?;
if page.items.is_empty() {
break;
}
posts.extend(page.items);
if posts.len() >= limit || page.cursor.is_none() {
break;
}
cursor = page.cursor;
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
}
posts.truncate(limit);
let posts = super::dedup_posts(posts);View on GitHub (pinned to 8600b91f42)