{"record":{"id":"8df771be2ca1e52a","repo":"quickwit-oss/tantivy","slug":"unsupported-8df771","errorCode":"Unsupported","errorMessage":"Async read is not supported.","messagePattern":"Async read is not supported\\.","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"warning","filePath":"common/src/file_slice.rs","lineNumber":30,"sourceCode":"/// Objects that represents files sections in tantivy.\n///\n/// By contract, whatever happens to the directory file, as long as a FileHandle\n/// is alive, the data associated with it cannot be altered or destroyed.\n///\n/// The underlying behavior is therefore specific to the `Directory` that\n/// created it. Despite its name, a [`FileSlice`] may or may not directly map to an actual file\n/// on the filesystem.\n\n#[async_trait]\npub trait FileHandle: 'static + Send + Sync + HasLen + fmt::Debug {\n    /// Reads a slice of bytes.\n    ///\n    /// This method may panic if the range requested is invalid.\n    fn read_bytes(&self, range: Range<usize>) -> io::Result<OwnedBytes>;\n\n    #[doc(hidden)]\n    async fn read_bytes_async(&self, _byte_range: Range<usize>) -> io::Result<OwnedBytes> {\n        Err(io::Error::new(\n            io::ErrorKind::Unsupported,\n            \"Async read is not supported.\",\n        ))\n    }\n}\n\n#[derive(Debug)]\n/// A File with it's length included.\npub struct WrapFile {\n    file: File,\n    len: usize,\n}\nimpl WrapFile {\n    /// Creates a new WrapFile and stores its length.\n    pub fn new(file: File) -> io::Result<Self> {\n        let len = file.metadata()?.len() as usize;\n        Ok(WrapFile { file, len })\n    }","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/common/src/file_slice.rs#L12-L48","documentation":"FileSlice's default read_bytes_async trait method is a stub that always returns io::Error(Unsupported, \"Async read is not supported.\"). Only backends that explicitly override read_bytes_async support async reads; the default (blocking, e.g. mmap-backed) implementation does not. This is a capability signal, not corruption.","triggerScenarios":"Awaiting read_bytes_async (e.g. via async search/segment open paths) on a FileSlice implementation that didn't override the async method — typically a std::fs or mmap-backed slice, or a custom impl using the default method.","commonSituations":"Using async index-opening APIs on files opened with blocking File/mmap; mixing sync FileSlice with async executors; custom FileSlice impls that only implemented the sync read_bytes.","solutions":["Use a FileSlice implementation that overrides read_bytes_async (e.g. an async-fs-backed wrapper)","Fall back to the blocking read_bytes when Unsupported is returned","Open the slice synchronously and wrap it in an in-memory OwnedBytes for async contexts","Implement read_bytes_async in your custom FileSlice impl"],"exampleFix":"// before\nlet bytes = file_slice.read_bytes_async(range).await?;\n// after\nlet bytes = match file_slice.read_bytes_async(range).await {\n    Err(e) if e.kind() == io::ErrorKind::Unsupported => file_slice.read_bytes(range)?,\n    other => other?,\n};","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"let bytes = match slice.read_bytes_async(range).await {\n    Ok(b) => Ok(b),\n    Err(e) if e.kind() == io::ErrorKind::Unsupported =>\n        tokio::task::block_in_place(|| slice.read_bytes(range)),\n    Err(e) => Err(e),\n}?;","preventionTips":["Check whether the FileSlice backend advertises async support before using async APIs","Prefer async-capable slice implementations (async-fs/object-store backed) in async code","Implement read_bytes_async in custom FileSlice impls","Route blocking slices through spawn_blocking/block_in_place"],"tags":["io","async","unsupported","file-slice"],"backgroundTag":"async-read-unsupported","analyzedSha":"b5d8deb80c26924e6b007a5b1a7630f35ca64de4","analyzedAt":"2026-09-05T13:20:51.521Z","contentChangedAt":"2026-09-05T13:20:51.521Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}