tonhowtf/omniget · error

resposta inesperada do Reddit (não é a lista de dois…

Error message

resposta inesperada do Reddit (não é a lista de dois listings)

What it means

`parse_thread_json` expects Reddit's permalink response to be a JSON array of exactly two listings (post listing, then comments listing). This error is thrown when the root JSON value is not an array at all — meaning the response body did not have the documented shape.

Solutions

  1. Log/inspect the raw response body before parsing to confirm it is the expected `[listing, listing]` array
  2. Check whether the request was redirected to a blocked/login page and handle that case before parsing
  3. Validate the response with a shape check (root.is_array() && root.len() >= 2) before calling parse_thread_json
  4. Update the parser if Reddit changed its permalink response structure

Example fix

// before
let (post, comments, mores) = parse_thread_json(&root)?;
// after
if !root.is_array() || root.as_array().map_or(true, |a| a.len() < 2) {
    anyhow::bail!("corpo inesperado: {}", serde_json::to_string(&root).unwrap_or_default());
}
let (post, comments, mores) = parse_thread_json(&root)?;
Defensive patterns

Strategy: type-guard

Validate before calling

fn looks_like_thread_json(root: &serde_json::Value) -> bool {
    root.as_array().map_or(false, |a| a.len() >= 2)
}

Type guard

fn is_two_listings(v: &Value) -> bool {
    v.is_array() && v.as_array().unwrap().len() >= 2
    && v[0].pointer("/data/children").is_some()
}

Try / catch

match parse_thread_json(&root) {
    Ok((post, comments, mores)) => /* ... */,
    Err(e) if e.to_string().contains("resposta inesperada") => {
        eprintln!("formato de resposta não reconhecido; salve o corpo bruto p/ debug");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling parse_thread_json (via expand, run, thread_from_fixture, or separa_os_dois_tipos_de_more) with a root Value that is an object, string, or null instead of the `[post, comments]` array — e.g. Reddit returned an HTML error page parsed loosely, an error JSON object, or a malformed fixture.

Common situations: Reddit serving an interstitial/error JSON (e.g. blocked message) instead of thread data; passing the wrong file to thread_from_fixture; Reddit API shape changes; HTML login/blocked pages being fed to the parser.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/reddit/thread.rs:193

                    .unwrap_or_default();
                let parent_id = s(data, "parent_id");
                if !parent_id.is_empty() {
                    mores.push(MoreRef {
                        parent_id,
                        children,
                    });
                }
            }
            _ => {}
        }
    }
}

/// A resposta de um permalink é `[listing do post, listing dos comentários]`.
pub fn parse_thread_json(root: &Value) -> Result<(Post, Vec<Comment>, Vec<MoreRef>)> {
    let arr = root
        .as_array()
        .ok_or_else(|| anyhow!("resposta inesperada do Reddit (não é a lista de dois listings)"))?;
    let post_data = arr
        .first()
        .and_then(|l| l.pointer("/data/children/0/data"))
        .ok_or_else(|| anyhow!("o post não veio na resposta (removido, privado ou apagado?)"))?;
    let post = parse_post(post_data);
    let mut flat = Vec::new();
    let mut mores = Vec::new();
    if let Some(children) = arr.get(1).and_then(|l| l.pointer("/data/children")) {
        parse_things(children, &mut flat, &mut mores);
    }
    Ok((post, flat, mores))
}

/// O `things` de `api/morechildren.json`.
pub fn parse_more_json(root: &Value) -> (Vec<Comment>, Vec<MoreRef>) {
    let mut flat = Vec::new();
    let mut mores = Vec::new();
    if let Some(things) = root

View on GitHub (pinned to 8600b91f42)