nautechsystems/nautilus_trader · error

Failed to insert into bar table: {e}

Error message

Failed to insert into bar table: {e}

What it means

add_bar wraps any sqlx error that occurs while binding/inserting a Bar row into the `bar` table inside anyhow::anyhow!, losing the concrete error type. It means the INSERT into the bar table failed at the database layer — typically a schema mismatch, constraint violation, or connection issue. The library throws it so callers get a single anyhow::Result with a descriptive message and the underlying sqlx error chained as source.

Source

Thrown at crates/infrastructure/src/sql/queries.rs:1379

                instrument_id = $1, step = $2, bar_aggregation = $3::bar_aggregation, price_type = $4::price_type, aggregation_source = $5::aggregation_source,
                open = $6, high = $7, low = $8, close = $9, volume = $10, ts_event = $11, ts_init = $12, updated_at = CURRENT_TIMESTAMP
        "#)
            .bind(bar.bar_type.instrument_id().to_string())
            .bind(bar_step)
            .bind(BarAggregationPg(bar.bar_type.spec().aggregation))
            .bind(PriceTypePg(bar.bar_type.spec().price_type))
            .bind(AggregationSourcePg(bar.bar_type.aggregation_source()))
            .bind(bar.open.to_string())
            .bind(bar.high.to_string())
            .bind(bar.low.to_string())
            .bind(bar.close.to_string())
            .bind(bar.volume.to_string())
            .bind(bar.ts_event.to_string())
            .bind(bar.ts_init.to_string())
            .execute(pool)
            .await
            .map(|_| ())
            .map_err(|e| anyhow::anyhow!("Failed to insert into bar table: {e}"))
    }

    /// Loads all `Bar` entries for `instrument_id` via the provided `pool`.
    ///
    /// # Errors
    ///
    /// Returns an error if the SQL SELECT or deserialization fails.
    pub async fn load_bars(
        pool: &PgPool,
        instrument_id: &InstrumentId,
    ) -> anyhow::Result<Vec<Bar>> {
        sqlx::query_as::<_, BarRow>(
            r#"SELECT * FROM "bar" WHERE instrument_id = $1 ORDER BY ts_event ASC"#,
        )
        .bind(instrument_id.to_string())
        .fetch_all(pool)
        .await
        .map(|rows| rows.into_iter().map(|row| row.0).collect())

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log/print the chained source (`e.source()`) or `{:?}` of the anyhow error to see the underlying sqlx message.
  2. Verify the `bar` table exists and matches the current schema by running the crate's migration/initialization (e.g. `create_bar_tables`) before inserting.
  3. Check DB connectivity and that the PgPool/SqlitePool is alive and credentials are valid.
  4. Ensure you are not inserting a duplicate bar for the same instrument_id/ts_event if a uniqueness constraint applies.
  5. Confirm column types can hold the stringified values (volume, ts_event, ts_init).

Example fix

// before
let pool = PgPool::connect_lazy(url)?;
queries::postgres::add_bar(&pool, &bar).await?;
// after
let pool = PgPool::connect(url).await?; // fail fast on bad connection
sqlx::migrate!().run(&pool).await?;      // ensure schema exists
queries::postgres::add_bar(&pool, &bar).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust
async fn bar_table_ready(pool: &sqlx::PgPool) -> anyhow::Result<()> {
    sqlx::query(r#"SELECT 1 FROM \"bar\" LIMIT 1"#).fetch_optional(pool).await
        .map(|_| ())
        .map_err(|e| anyhow::anyhow!("bar table not initialized: {e}"))
}

Try / catch

// Rust
match queries::postgres::add_bar(&pool, &bar).await {
    Ok(()) => (),
    Err(e) => {
        tracing::error!(source = ?std::error::Error::source(&e), "bar insert failed");
        return Err(e);
    }
}

Prevention

When it happens

Trigger: Calling add_bar when the `bar` table does not exist or was created with an older schema, when bar fields exceed column types/precision (e.g. oversized instrument_id or volume), when the connection pool is dead, or when a UNIQUE/PRIMARY KEY constraint (instrument_id + ts_event) is violated.

Common situations: Running against a Postgres/SQLite database migrated with an outdated schema version; switching between SQLite and Postgres backends with incompatible types; network drop between pool creation and execute; inserting a duplicate bar for the same instrument/timestamp.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/af5796f4797a4330. Report an issue: GitHub.