nautechsystems/nautilus_trader · error
Failed to send query add_bar to database message handler: {e
Error message
Failed to send query add_bar to database message handler: {e} What it means
add_bar wraps the Bar in DatabaseQuery::AddBar and sends it over self.tx to the database message handler; on send failure anyhow::anyhow! raises this error. Sends fail only when the receiver half was dropped, i.e. the background writer task is gone. Note the message text says add_bar while some sibling methods (e.g. add_custom_data) reuse other labels — the mechanism is identical.
Source
Thrown at crates/infrastructure/src/sql/cache.rs:1065
});
Ok(rx.recv()?)
}
fn add_funding_rate(&self, _funding_rate: &FundingRateUpdate) -> anyhow::Result<()> {
anyhow::bail!("add_funding_rate not implemented for PostgreSQL cache adapter")
}
fn load_funding_rates(
&self,
_instrument_id: &InstrumentId,
) -> anyhow::Result<Vec<FundingRateUpdate>> {
anyhow::bail!("load_funding_rates not implemented for PostgreSQL cache adapter")
}
fn add_bar(&self, bar: &Bar) -> anyhow::Result<()> {
let query = DatabaseQuery::AddBar(bar.to_owned());
self.tx.send(query).map_err(|e| {
anyhow::anyhow!("Failed to send query add_bar to database message handler: {e}")
})
}
fn load_bars(&self, instrument_id: &InstrumentId) -> anyhow::Result<Vec<Bar>> {
let pool = self.pool.clone();
let instrument_id = instrument_id.to_owned();
let (tx, rx) = std::sync::mpsc::channel();
tokio::spawn(async move {
let result = DatabaseQueries::load_bars(&pool, &instrument_id).await;
match result {
Ok(bars) => {
if let Err(e) = tx.send(bars) {
log::error!("Failed to send bars for instrument {instrument_id}: {e:?}");
}
}
Err(e) => {
log::error!("Failed to load bars for instrument {instrument_id}: {e:?}");View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure the cache adapter and its handler task are alive before bar writes
- Recreate the adapter after shutdown rather than reusing the dropped-channel instance
- Find and fix why the handler task ended (startup failure, panic) from its logs
- Guard bar writes with error handling when persistence loss is acceptable
Defensive patterns
Strategy: try-catch
Try / catch
try:
cache.add_bar(bar)
except Exception as e:
if "Failed to send query add_bar" in str(e):
logger.warning("bar persistence skipped: handler down")
return # or buffer bar for retry Prevention
- Buffer bars locally and flush when the adapter is restored
- Stop backfill jobs before shutting down the adapter
- Track adapter liveness with a flag checked before writes
- Review handler panics in logs to prevent silent channel closure
When it happens
Trigger: Calling add_bar (or py_add_bar) after the handler task exited — adapter shutdown, aborted task, or handler that died at startup.
Common situations: Bar persistence during a long backfill while the DB adapter was recreated or disconnected; shutdown ordering bug where the cache is dropped before writers stop; handler crashed earlier on a bad batch.
Related errors
- Failed to send query add_quote to database message handler:
- Failed to send query add_trade to database message handler:
- Failed to send query add_signal to database message handler:
- Failed to send query index_order_position to database messag
- Failed to send query index_order_clients to database message
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/cb9a097430ee1b58.
Report an issue: GitHub.