influxdata/influxdb · error · Error
wal is shutdown and not accepting writes
Error message
wal is shutdown and not accepting writes
What it means
Error::Shutdown is raised by the influxdb3_wal WriteBuffer once the WAL has been shut down and will no longer persist incoming writes. After shutdown, buffering a write would silently drop data, so the library rejects any new write with this error. It signals a lifecycle violation: writes must stop before (or be routed away from) a shutdown WAL.
Solutions
- Stop sending writes once shutdown() has been called; check the WAL/buffer state before issuing writes in embedded usage.
- Drain in-flight write requests before calling shutdown, and return a clean error to clients during the draining window.
- Treat this error as a client-side signal to stop retrying and report 'server is shutting down' to the user.
- In application code, guard with a lifecycle flag or channel closed check so writes are never issued post-shutdown.
Example fix
// before
wal.shutdown().await;
wal.write_buffer(buffer, Gen1Duration::default()).await?; // panics/errors: wal is shutdown
// after
wal.shutdown().await;
if !wal.is_shutdown() {
wal.write_buffer(buffer, Gen1Duration::default()).await?;
} else {
return Err("server is shutting down; write rejected");
} Defensive patterns
Strategy: try-catch
Validate before calling
// embedded usage: check state before writing
if wal.is_shutdown() {
return Err(WriteRejected::ShuttingDown);
} Type guard
fn is_shutdown(err: &influxdb3_wal::Error) -> bool { matches!(err, influxdb3_wal::Error::Shutdown) } Try / catch
match wal.write_buffer(buffer, gen1).await {
Err(influxdb3_wal::Error::Shutdown) => /* stop retrying, signal shutdown to client */,
Err(e) => return Err(e.into()),
Ok(_) => {},
} Prevention
- Drain and close client write paths before calling shutdown().
- Keep a lifecycle flag (AtomicBool/tokio::sync::Notify) mirroring WAL state in embedded users.
- Never retry writes that fail with Shutdown — it is terminal, not transient.
When it happens
Trigger: Calling write_buffer (or another write-path method) on a WalObjectStore/WriteBuffer whose state has been set to ShuttingDown/Shut down, typically after wal_buffer.shutdown() was invoked or the server is stopping.
Common situations: A write request races with a graceful server shutdown; a caller keeps a WriteBuffer handle alive after calling shutdown; tests or embedded users issuing writes after teardown; double-shutdown followed by a straggler write from an open connection.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- lost backend
- lost HTTP/gRPC service
- another process has written to the WAL ahead of this one
- bitcode error
- crc32 checksum mismatch
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/13a89a68b02d19b1.
Report an issue: GitHub.
Appendix: source
Thrown at influxdb3_wal/src/lib.rs:52
#[derive(Debug, Error)]
pub enum Error {
#[error("wal buffer full with {0} ops")]
BufferFull(usize),
#[error("error writing wal file: {0}")]
WriteError(String),
#[error("deserialize error: {0}")]
Serialize(#[from] crate::serialize::Error),
#[error("join error: {0}")]
Join(#[from] tokio::task::JoinError),
#[error("object store error: {0}")]
ObjectStoreError(#[from] ::object_store::Error),
#[error("wal is shutdown and not accepting writes")]
Shutdown,
#[error("invalid gen1 duration {0}. Must be one of 1m, 5m, 10m")]
InvalidGen1Duration(String),
#[error("invalid WAL file path")]
InvalidWalFilePath,
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[async_trait]
pub trait Wal: Debug + Send + Sync + 'static {
/// Buffer writes ops into the buffer, but returns before the operation is persisted to the WAL.
async fn write_ops_unconfirmed(&self, op: Vec<WalOp>) -> Result<(), Error>;
/// Writes the ops into the buffer and waits until the WAL file is persisted. When this returns
/// the operations are durable in the configured object store and the file notifier has beenView on GitHub (pinned to 06200ef96b)