{"record":{"id":"0876cf097208895c","repo":"quickwit-oss/quickwit","slug":"reading-file-panicked","errorCode":null,"errorMessage":"reading file panicked","messagePattern":"reading file panicked","errorType":"exception","errorClass":"StorageError","httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-storage/src/local_file_storage.rs","lineNumber":235,"sourceCode":"        let full_path = self.full_path(path)?;\n        tokio::task::spawn_blocking(move || {\n            use std::io::{Read, Seek};\n            // we run these io in a spawn_blocking so there is no scheduling delay between each\n            // step, as there would be if using tokio async File.\n            let mut file = std::fs::File::open(full_path)?;\n            file.seek(SeekFrom::Start(range.start as u64))?;\n            let _in_flight_guards = object_storage_get_slice_in_flight_guards(range.len());\n            let mut content_bytes: Vec<u8> = Vec::with_capacity(range.len());\n            #[allow(clippy::uninit_vec)]\n            unsafe {\n                content_bytes.set_len(range.len());\n            }\n            file.read_exact(&mut content_bytes)?;\n            Ok(OwnedBytes::new(content_bytes))\n        })\n        .await\n        .map_err(|_| {\n            StorageErrorKind::Internal.with_error(anyhow::anyhow!(\"reading file panicked\"))\n        })?\n    }\n\n    #[tracing::instrument(\n        name = \"storage.local_file.get_slice_stream\",\n        skip(self),\n        level = \"debug\"\n    )]\n    async fn get_slice_stream(\n        &self,\n        path: &Path,\n        range: Range<usize>,\n    ) -> StorageResult<Box<dyn AsyncRead + Send + Unpin>> {\n        let full_path = self.full_path(path)?;\n        let mut file = tokio::fs::File::open(&full_path).await?;\n        file.seek(SeekFrom::Start(range.start as u64)).await?;\n        Ok(Box::new(file.take(range.len() as u64)))\n    }","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-storage/src/local_file_storage.rs#L217-L253","documentation":"This error is thrown when the blocking task spawned to read a byte range from a local file panics. `get_slice` runs the read inside `spawn_blocking`; the `.map_err(|_| ...)` discards the panic payload because the JoinError gives no payload access here, and wraps it as an Internal storage error. It means the read thread crashed unexpectedly, not that the file is missing.","triggerScenarios":"Calling `Storage::get_slice` on a LocalFileStorage when the spawned blocking closure panics — e.g. the file is truncated/deleted between length check and `read_exact` (unexpected EOF in some paths), or a bug in the closure (bad range arithmetic causing a slicing panic, poisoned state).","commonSituations":"File mutated or removed concurrently by log rotation or another process while Quickwit reads a hotcache/split slice; filesystem errors surfacing as panics; a Quickwit bug in range computation on zero-length or very small files.","solutions":["Check the process logs/stderr for the original panic message and backtrace to find the real cause","Verify the file still exists and has not been truncated since the size was read (`ls -l`, compare with split metadata)","Re-download or re-index the affected split if it is corrupted","Retry the search; if reproducible on a specific split, inspect the split for corruption with `quickwit tool` commands","Report a bug with the panic backtrace if it occurs on intact files"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let md = tokio::fs::metadata(&file_path).await?;\nif !md.is_file() || md.len() == 0 { /* skip or re-fetch split */ }","typeGuard":null,"tryCatchPattern":"match storage.get_slice(&path, range).await {\n    Ok(bytes) => use(bytes),\n    Err(e) if e.kind() == StorageErrorKind::Internal => log::error!(\"read panicked: {e}\"),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Watch process logs for panics in storage code and treat any occurrence as a bug or file corruption","Avoid mutating/deleting split files while the search server is running","Verify split integrity after unexpected crashes or disk-full events","Retry once; a reproducible panic on an intact file should be reported upstream"],"tags":["storage","panic","local-fs","internal"],"backgroundTag":"file-read-failed","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"}