nautechsystems/nautilus_trader · error
Failed to send query to database message handler: {e}
Error message
Failed to send query to database message handler: {e} What it means
Thrown by the SQL cache's `add` when sending a `DatabaseQuery::Add(key, value)` over the internal mpsc channel to the dedicated database message-handler task fails. A send fails only when the receiver side has been dropped/shut down, meaning the writer task is no longer processing queries. The write is not performed.
Source
Thrown at crates/infrastructure/src/sql/cache.rs:910
"delete_order not implemented for PostgreSQL cache adapter: {client_order_id}"
)
}
fn delete_position(&self, position_id: &PositionId) -> anyhow::Result<()> {
anyhow::bail!("delete_position not implemented for PostgreSQL cache adapter: {position_id}")
}
fn delete_account_event(&self, account_id: &AccountId, event_id: &str) -> anyhow::Result<()> {
anyhow::bail!(
"delete_account_event not implemented for PostgreSQL cache adapter: {account_id}, {event_id}"
)
}
fn add(&self, key: String, value: Bytes) -> anyhow::Result<()> {
let query = DatabaseQuery::Add(key, value.into());
self.tx
.send(query)
.map_err(|e| anyhow::anyhow!("Failed to send query to database message handler: {e}"))
}
fn add_currency(&self, currency: &Currency) -> anyhow::Result<()> {
let query = DatabaseQuery::AddCurrency(*currency);
self.tx.send(query).map_err(|e| {
anyhow::anyhow!("Failed to query add_currency to database message handler: {e}")
})
}
fn add_instrument(&self, instrument: &InstrumentAny) -> anyhow::Result<()> {
let query = DatabaseQuery::AddInstrument(instrument.clone());
self.tx.send(query).map_err(|e| {
anyhow::anyhow!("Failed to send query add_instrument to database message handler: {e}")
})
}
fn add_instrument_close(&self, close: &InstrumentClose) -> anyhow::Result<()> {
self.txView on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the cache database adapter (and its message-handler task) is created, connected, and kept alive before calling `add`.
- Check logs from the receiver task for a panic that dropped the channel.
- Rebuild/reconnect the cache database client and retry the write.
- Guard Python code so `py_add` is not called after the adapter has been stopped.
Example fix
// before
self.tx.send(query).map_err(|e| anyhow::anyhow!("Failed to send query to database message handler: {e}"))?;
// after
if self.tx.is_closed() {
return Err(anyhow::anyhow!("Database message handler is not running; cannot persist cache entry"));
}
self.tx.send(query).map_err(|e| anyhow::anyhow!("Failed to send query to database message handler: {e}"))?; Defensive patterns
Strategy: try-catch
Validate before calling
# Python: verify adapter is writable before add
if not cache_db_adapter.is_running:
raise RuntimeError("Cache database adapter is not running") Try / catch
try:
cache.add(key, value)
except RuntimeError as e:
logger.error("Cache database writer unavailable: %s", e) Prevention
- Keep the cache database adapter connected for the whole session
- Stop writes before disconnecting the adapter
- Monitor the writer task's health/panics
- Check send-channel liveness before bulk writes
When it happens
Trigger: Calling `add` (exposed to Python as `py_add`) after the backing task/thread running the message loop has exited or been dropped, so the `tx.send(query)` returns a SendError.
Common situations: Adapter shutdown ordering — cache database client stopped or its connection task panicked while the cache is still being written; a background panic killed the receiver; calling add during teardown/atexit from Python.
Related errors
- Failed to query add_currency to database message handler: {e
- Failed to send query add_instrument to database message hand
- Failed to send query add_instrument_close to database messag
- Failed to send query add_account to database message handler
- Failed to send query add_order to database message handler:
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/671be8fe098ab205.
Report an issue: GitHub.