{"record":{"id":"68c2aca9ac6d3744","repo":"nautechsystems/nautilus_trader","slug":"failed-to-flush-database-e","errorCode":null,"errorMessage":"Failed to flush database: {e}","messagePattern":"Failed to flush database: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/infrastructure/src/redis/cache.rs","lineNumber":426,"sourceCode":"    }\n\n    /// Sends a flush command through the background task channel and blocks\n    /// until it completes. Safe to call from any runtime context.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the command channel is closed or the reply is lost.\n    pub fn flushdb_sync(&self) -> anyhow::Result<()> {\n        let (reply_tx, reply_rx) = mpsc::sync_channel(1);\n        let cmd = DatabaseCommand {\n            op_type: DatabaseOperation::Flush(reply_tx),\n            key: None,\n            payload: None,\n        };\n        self.tx\n            .send(cmd)\n            .map_err(|e| anyhow::anyhow!(\"{FAILED_TX_CHANNEL}: {e}\"))?;\n        blocking_recv(&reply_rx).map_err(|e| anyhow::anyhow!(\"Failed to flush database: {e}\"))?;\n        Ok(())\n    }\n\n    /// Retrieves all keys matching the given `pattern` from Redis for this trader.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the underlying Redis scan operation fails.\n    pub async fn keys(&mut self, pattern: &str) -> anyhow::Result<Vec<String>> {\n        let pattern = format!(\"{}{REDIS_DELIMITER}{pattern}\", self.trader_key);\n        DatabaseQueries::scan_keys(&mut self.con, pattern).await\n    }\n\n    /// Reads the value(s) associated with `key` for this trader from Redis.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the underlying Redis read operation fails.","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/infrastructure/src/redis/cache.rs#L408-L444","documentation":"Raised by RedisCache::flushdb_sync when blocking_recv on the reply channel fails — the reply sender was dropped without a successful result, typically because the background task aborted or the reply channel closed while awaiting the Flush confirmation.","triggerScenarios":"Calling flushdb_sync; the command is sent successfully, but the background task dies (panic, abort, cancellation) before replying, so blocking_recv returns an error which is wrapped as 'Failed to flush database: {e}'.","commonSituations":"Redis connection dropping mid-operation, background task being cancelled during shutdown, timeouts or panics in the worker while processing the flush command.","solutions":["Inspect the wrapped error {e} to find why the reply channel closed (panic/abort/disconnect)","Ensure the Redis server is reachable and the background task stays alive for the duration of the flush","Retry the flush after re-establishing the cache connection","Avoid dropping or cancelling the cache task while a flushdb_sync call is in flight"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// ensure connection is alive before flushing\nif !cache.check_connection() {\n    anyhow::bail!(\"redis connection is down; cannot flush\");\n}","typeGuard":null,"tryCatchPattern":"match cache.flushdb_sync() {\n    Ok(()) => (),\n    Err(e) if e.to_string().starts_with(\"Failed to flush database\") => {\n        log::warn!(\"flush reply lost, retrying: {e:#}\");\n        cache.flushdb_sync().context(\"flush retry failed\")?;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Avoid cancelling the background task while commands are in flight","Monitor Redis connectivity and reconnect proactively","Inspect the wrapped inner error to distinguish panic vs disconnect"],"tags":["redis","channel-closed","flush"],"backgroundTag":"broken-pipe","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}