{"record":{"id":"bd5780963f4bf5f1","repo":"quickwit-oss/quickwit","slug":"failed-to-find-offset-for-split","errorCode":null,"errorMessage":"failed to find offset for split {}","messagePattern":"failed to find offset for split (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-search/src/fetch_docs.rs","lineNumber":67,"sourceCode":"    let mut split_fetch_docs_futures = Vec::new();\n\n    let split_offsets_map: HashMap<&str, &SplitIdAndFooterOffsets> = splits\n        .iter()\n        .map(|split| (split.split_id.as_str(), split))\n        .collect();\n\n    // We sort global hit addrs in order to allow for the grouby.\n    global_doc_addrs.sort_by(|a, b| a.split.cmp(&b.split));\n    for (split_id, global_doc_addrs) in global_doc_addrs\n        .iter()\n        .chunk_by(|global_doc_addr| global_doc_addr.split.as_str())\n        .into_iter()\n    {\n        let global_doc_addrs: Vec<GlobalDocAddress> =\n            global_doc_addrs.into_iter().cloned().collect();\n        let split_and_offset = split_offsets_map\n            .get(split_id)\n            .ok_or_else(|| anyhow::anyhow!(\"failed to find offset for split {}\", split_id))?;\n        let split_id = split_id.to_string();\n        split_fetch_docs_futures.push(\n            fetch_docs_in_split(\n                searcher_context.clone(),\n                global_doc_addrs,\n                index_storage.clone(),\n                split_and_offset,\n                doc_mapper.clone(),\n                snippet_request_opt,\n            )\n            .map_err(move |e| e.context(format!(\"split_id={split_id}\"))),\n        );\n    }\n\n    let split_fetch_docs: Vec<Vec<(GlobalDocAddress, Document)>> =\n        futures::future::try_join_all(split_fetch_docs_futures)\n            .await\n            .map_err(|error| {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-search/src/fetch_docs.rs#L49-L85","documentation":"During the fetch-docs phase of distributed search, results grouped by split_id are looked up in a map of split_id -> split offsets built from the search hits. If a split appears in the hit groups but has no entry in the split offsets map, this invariant is violated and the error is thrown. It indicates the caller-supplied hit list references a split that was never resolved to offsets.","triggerScenarios":"Calling fetch_docs with a set of hits whose split_id has no corresponding entry in split_offsets_map — e.g. hits from a metastore/search response that include a split not covered by the offset resolution step.","commonSituations":"Stale or mismatched search responses (split deleted between search and fetch); custom search callers constructing hits manually; internal inconsistencies after split migration or retention deletion.","solutions":["Verify the split_id in the error actually exists in the index and its splits were resolved before fetch_docs (check the search response's split_offsets).","Re-run the search against a fresh metastore snapshot; the split may have been removed mid-flight.","If building hits programmatically, ensure every hit's split is passed through the same offset-resolution step that populates split_offsets_map."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let missing: Vec<_> = hits.iter().map(|h| h.split_id()).filter(|s| !split_offsets_map.contains_key(*s)).collect();\nif !missing.is_empty() { return Err(anyhow!(\"unresolved splits: {missing:?}\")); }","typeGuard":null,"tryCatchPattern":"match fetch_docs(...).await {\n    Ok(docs) => docs,\n    Err(e) if e.to_string().contains(\"failed to find offset for split\") => {\n        // stale search response; retry the search to rebuild split offsets\n        retry_search().await\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Always build hits through the standard search pipeline so offsets are resolved","Retry the whole search when splits may have been deleted between phases","Keep metastore snapshots consistent across search and fetch phases"],"tags":["rust","search","splits","internal"],"backgroundTag":"record-not-found","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}