{"record":{"id":"13a89a68b02d19b1","repo":"influxdata/influxdb","slug":"wal-is-shutdown-and-not-accepting-writes","errorCode":null,"errorMessage":"wal is shutdown and not accepting writes","messagePattern":"wal is shutdown and not accepting writes","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"influxdb3_wal/src/lib.rs","lineNumber":52,"sourceCode":"\n#[derive(Debug, Error)]\npub enum Error {\n    #[error(\"wal buffer full with {0} ops\")]\n    BufferFull(usize),\n\n    #[error(\"error writing wal file: {0}\")]\n    WriteError(String),\n\n    #[error(\"deserialize error: {0}\")]\n    Serialize(#[from] crate::serialize::Error),\n\n    #[error(\"join error: {0}\")]\n    Join(#[from] tokio::task::JoinError),\n\n    #[error(\"object store error: {0}\")]\n    ObjectStoreError(#[from] ::object_store::Error),\n\n    #[error(\"wal is shutdown and not accepting writes\")]\n    Shutdown,\n\n    #[error(\"invalid gen1 duration {0}. Must be one of 1m, 5m, 10m\")]\n    InvalidGen1Duration(String),\n\n    #[error(\"invalid WAL file path\")]\n    InvalidWalFilePath,\n}\n\npub type Result<T, E = Error> = std::result::Result<T, E>;\n\n#[async_trait]\npub trait Wal: Debug + Send + Sync + 'static {\n    /// Buffer writes ops into the buffer, but returns before the operation is persisted to the WAL.\n    async fn write_ops_unconfirmed(&self, op: Vec<WalOp>) -> Result<(), Error>;\n\n    /// Writes the ops into the buffer and waits until the WAL file is persisted. When this returns\n    /// the operations are durable in the configured object store and the file notifier has been","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_wal/src/lib.rs#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nwal.shutdown().await;\nwal.write_buffer(buffer, Gen1Duration::default()).await?; // panics/errors: wal is shutdown\n// after\nwal.shutdown().await;\nif !wal.is_shutdown() {\n    wal.write_buffer(buffer, Gen1Duration::default()).await?;\n} else {\n    return Err(\"server is shutting down; write rejected\");\n}","handlingStrategy":"try-catch","validationCode":"// embedded usage: check state before writing\nif wal.is_shutdown() {\n    return Err(WriteRejected::ShuttingDown);\n}","typeGuard":"fn is_shutdown(err: &influxdb3_wal::Error) -> bool { matches!(err, influxdb3_wal::Error::Shutdown) }","tryCatchPattern":"match wal.write_buffer(buffer, gen1).await {\n    Err(influxdb3_wal::Error::Shutdown) => /* stop retrying, signal shutdown to client */,\n    Err(e) => return Err(e.into()),\n    Ok(_) => {},\n}","preventionTips":["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."],"tags":["rust","wal","lifecycle","shutdown"],"backgroundTag":"invalid-state-transition","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}