tonhowtf/omniget · error

Reddit retornou HTTP

Error message

Reddit retornou HTTP {}

What it means

fetch_post_data requests the Reddit JSON API (.json endpoint) and checks the HTTP status before parsing. If Reddit responds with a non-2xx status (404 removed post, 403 quarantine/private, 429 rate limit, 5xx outage), the library surfaces it as this anyhow error with the status code embedded in the message, aborting media-info extraction.

Solutions

  1. Verify the post URL opens in a browser (post not deleted/removed) before calling the API.
  2. Inspect the status code in the message: 429 means slow down / add retry with backoff; 403 may require authentication headers or a valid User-Agent.
  3. Retry after a delay for transient 5xx responses; consider adding a proper User-Agent string to the reqwest client to reduce blocking.
  4. If 403 persists, check whether the subreddit is quarantined/private and use authenticated access.

Example fix

// before
let resp = self.client.get(&url).header("Accept", "application/json").send().await?;
if !resp.status().is_success() {
    return Err(anyhow!("Reddit retornou HTTP {}", resp.status()));
}
// after: add User-Agent and retry on transient failures
let resp = self.client.get(&url)
    .header("Accept", "application/json")
    .header("User-Agent", "omniget/1.0")
    .send().await?;
if resp.status() == reqwest::StatusCode::TOO_MANY_REQUESTS {
    tokio::time::sleep(Duration::from_secs(2)).await;
    return self.fetch_post_data(post_id).await; // retry
}
if !resp.status().is_success() {
    return Err(anyhow!("Reddit retornou HTTP {}", resp.status()));
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-check reachability before calling the library
let head = reqwest::Client::new()
    .head(&post_url)
    .header("User-Agent", "omniget/1.0")
    .send().await?;
if head.status() == reqwest::StatusCode::NOT_FOUND {
    return Err(anyhow!("Post is gone (404); skip"));
}

Try / catch

match native_get_media_info(url).await {
    Err(e) if e.to_string().contains("HTTP 429") => schedule_retry_with_backoff(url),
    Err(e) if e.to_string().contains("HTTP 4") => show_user("Post unavailable"),
    Err(e) => retry_transient(url, e),
    Ok(info) => use(info),
}

Prevention

When it happens

Trigger: Reddit's JSON endpoint returns 404/403/429/5xx during response.send() in fetch_post_data, called from native_get_media_info for a given post URL.

Common situations: Deleted or removed posts, private/quarantined subreddits, Reddit rate limiting (429) from too many requests without OAuth, or Reddit CDN/API outages returning 5xx.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/platforms/reddit.rs:131

        if Self::is_share_link(url) {
            return redirect::resolve_redirect(&self.client, url).await;
        }

        Ok(url.to_string())
    }

    async fn fetch_post_data(&self, post_id: &str) -> anyhow::Result<serde_json::Value> {
        let url = format!("https://www.reddit.com/comments/{}.json", post_id);

        let response = self
            .client
            .get(&url)
            .header("Accept", "application/json")
            .send()
            .await?;

        if !response.status().is_success() {
            return Err(anyhow!("Reddit retornou HTTP {}", response.status()));
        }

        let json: serde_json::Value = response.json().await?;

        if !json.is_array() {
            return Err(anyhow!("Post not found"));
        }

        json.as_array()
            .and_then(|arr| arr.first())
            .and_then(|listing| listing.pointer("/data/children/0/data"))
            .cloned()
            .ok_or_else(|| anyhow!("Post not found"))
    }

    fn construct_audio_url(fallback_url: &str) -> Vec<String> {
        let video = fallback_url.split('?').next().unwrap_or(fallback_url);
        let mut candidates = Vec::new();

View on GitHub (pinned to 8600b91f42)