quickwit-oss/quickwit · warning · io::Error (from StorageError)
dynamic message: storage_err.source.to_string() converted in
Error message
dynamic message: storage_err.source.to_string() converted into io::Error (NotFound or Other depending on StorageErrorKind)
What it means
`From<StorageError> for io::Error` maps a storage failure into the standard library error type: NotFound keeps io::ErrorKind::NotFound, every other kind becomes Other, and the error text is just the source error's stringified message. As the in-code TODO notes, the original structured context (kind, source chain) is swallowed, so callers relying on downcasting lose detail.
Source
Thrown at quickwit/quickwit-storage/src/error.rs:87
impl StorageErrorKind {
/// Creates a StorageError.
pub fn with_error(self, source: impl Into<anyhow::Error>) -> StorageError {
StorageError {
kind: self,
source: Arc::new(source.into()),
retry_after: None,
}
}
}
impl From<StorageError> for io::Error {
fn from(storage_err: StorageError) -> Self {
let io_error_kind = match storage_err.kind() {
StorageErrorKind::NotFound => io::ErrorKind::NotFound,
_ => io::ErrorKind::Other,
};
// TODO: This is swallowing the context of the source error.
io::Error::new(io_error_kind, storage_err.source.to_string())
}
}
/// Generic StorageError.
#[derive(Debug, Clone, Error)]
#[error("storage error(kind={kind:?}, source={source})")]
#[allow(missing_docs)]
pub struct StorageError {
pub kind: StorageErrorKind,
#[source]
source: Arc<anyhow::Error>,
/// Server-suggested delay before the next retry, if provided (e.g. from `x-amz-retry-after`).
pub(crate) retry_after: Option<Duration>,
}
/// Generic Result type for storage operations.
pub type StorageResult<T> = Result<T, StorageError>;
View on GitHub (pinned to a39730c5cd)
Solutions
- Inspect the io error's Display string to recover the underlying storage message.
- Match on the io::ErrorKind only as NotFound vs other — do not expect finer kinds through this conversion.
- Preserve the original StorageError in your own error type instead of converting early, so kind() and source() stay available.
- If the swallowed context matters for debugging, check storage backend logs/metrics at the time of the failure.
Example fix
// before let io_err = io::Error::from(storage_err); // after let io_err = io::Error::new(io_err.kind(), storage_err); // keep original error where the API permits // or better: propagate StorageError instead of converting
Defensive patterns
Strategy: try-catch
Type guard
fn is_storage_not_found(err: &std::io::Error) -> bool {
err.kind() == std::io::ErrorKind::NotFound
} Try / catch
match operation().await {
Err(e) if e.kind() == std::io::ErrorKind::NotFound => handle_missing(),
Err(other) => {
// kind is Other; the Display string is the only remaining storage detail
log::warn!("storage failure: {other}");
}
Ok(v) => v,
} Prevention
- Preserve StorageError end-to-end instead of converting to io::Error early.
- Do not rely on fine-grained io::ErrorKind through this conversion — only NotFound is preserved.
- Check storage backend logs/credentials when you see Other-kind io errors.
When it happens
Trigger: Any code path that converts a StorageError into io::Error — e.g. a reader/writer expecting std::io errors receiving a failure from an S3/Azure/GCS/Local storage backend, with the storage kind not being NotFound.
Common situations: Object storage outages, missing credentials/expired tokens surfacing as Other-kind io errors, network failures during split reads, file permissions issues on local storage — all collapsed to a plain message string.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Invalid file name in path {path:?}
- `append_records` should be called with `position_opt: None`
- failed to run mrecordlog operation
- stdin cannot be checkpointed
- Unexpected span kind: {}
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/76e97432d296651d.
Report an issue: GitHub.