tonhowtf/omniget · error · anyhow::Error

não foi possível ler

Error message

não foi possível ler {}

What it means

After exhausting all TRIES retry attempts because of network-level errors (connection failures, timeouts, reqwest::Error), get_text() falls through the loop and returns this generic failure naming the URL. It means the body could never be retrieved at the transport level.

Solutions

  1. Check internet connectivity and DNS resolution for the host
  2. Retry later if the site is down
  3. Check proxy/VPN/firewall settings that may block the connection
  4. Increase retry patience or run again on a more stable network
Defensive patterns

Strategy: retry

Try / catch

match fetcher.get_text(url).await {
    Err(e) if e.to_string().contains("não foi possível ler") => {
        if online() { return fetcher.get_text(url).await; }
        return Err(e);
    }
    other => other,
}

Prevention

When it happens

Trigger: All retry attempts in get_text ended with Err(e) from client.get(url).send() (DNS failure, connection refused/reset, TLS error, timeout), so control reaches the final Err(anyhow!("não foi possível ler {}")) after the loop.

Common situations: No internet / DNS misconfiguration; corporate firewall blocking medium.com; server dropping connections; proxy misconfiguration; long outage exceeding the retry budget.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/blogs/mod.rs:196

                    let retry = r
                        .headers()
                        .get(reqwest::header::RETRY_AFTER)
                        .and_then(|v| v.to_str().ok())
                        .and_then(|v| v.trim().parse::<u64>().ok())
                        .map(Duration::from_secs);
                    tokio::time::sleep(retry.unwrap_or(wait)).await;
                    wait *= 2;
                }
                Ok(r) => return Err(anyhow!("HTTP {} em {}", r.status(), url)),
                Err(e) if attempt < TRIES => {
                    tokio::time::sleep(wait).await;
                    wait *= 2;
                    let _ = e;
                }
                Err(e) => return Err(e.into()),
            }
        }
        Err(anyhow!("não foi possível ler {}", url))
    }

    /// GET com JSON de volta. Tolera o prefixo anti-sequestro do Medium.
    pub async fn get_json(&self, url: &str) -> Result<serde_json::Value> {
        let text = self.get_text(url).await?;
        let body = strip_json_prefix(&text);
        serde_json::from_str(body)
            .map_err(|e| anyhow!("o servidor respondeu algo que não é JSON ({}): {}", e, url))
    }
}

/// O Medium serve JSON prefixado com `])}while(1);</x>` para que ninguém
/// consiga incluir a resposta como `<script>`. É lixo antes do primeiro `{`
/// ou `[`; cortar é obrigatório antes de parsear.
pub fn strip_json_prefix(text: &str) -> &str {
    let t = text.trim_start();
    if t.starts_with('{') || t.starts_with('[') {
        return t;

View on GitHub (pinned to 8600b91f42)