nautechsystems/nautilus_trader · error

Cannot persist bar with composite bar type {}: the bar table

Error message

Cannot persist bar with composite bar type {}: the bar table stores only the standard form; standardize the bar type before persisting

What it means

Thrown by `add_bar` when persisting a `Bar` whose `BarType` is composite (e.g. with aggregation transforms or non-standard composition). The bars table only stores the standard bar form, so the caller must standardize the bar type before persisting; the library refuses to silently transform or lose composite information.

Source

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

    ) -> anyhow::Result<Vec<QuoteTick>> {
        sqlx::query_as::<_, QuoteTickRow>(
            r#"SELECT * FROM "quote" 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())
        .map_err(|e| anyhow::anyhow!("Failed to load quotes: {e}"))
    }

    /// Inserts a `Bar` entry via the provided `pool`.
    ///
    /// # Errors
    ///
    /// Returns an error if the SQL INSERT operation fails.
    pub async fn add_bar(pool: &PgPool, bar: &Bar) -> anyhow::Result<()> {
        if bar.bar_type.is_composite() {
            anyhow::bail!(
                "Cannot persist bar with composite bar type {}: the bar table stores only \
                 the standard form; standardize the bar type before persisting",
                bar.bar_type,
            );
        }

        let bar_step = i32::try_from(bar.bar_type.spec().step.get())
            .map_err(|e| anyhow::anyhow!("invalid bar step: {e}"))?;

        sqlx::query(r#"
            INSERT INTO "bar" (
                instrument_id, step, bar_aggregation, price_type, aggregation_source, open, high, low, close, volume, ts_event, ts_init, created_at, updated_at
            ) VALUES (
                $1, $2, $3::bar_aggregation, $4::price_type, $5::aggregation_source, $6, $7, $8, $9, $10, $11, $12, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
            )
            ON CONFLICT (id)
            DO UPDATE
            SET

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Call `bar.bar_type.standardize()` (build the bar from the standardized bar type) before persisting.
  2. Persist only bars with standard bar types; keep composite bars in memory or a separate store if needed.
  3. Filter composite bars out at the subscription/handler level before writing to the SQL cache.

Example fix

// before
queries.add_bar(&pool, &bar).await?;

// after
let standard_bar = Bar::new(bar.bar_type.standardize(), bar.open, bar.high, bar.low, bar.close, bar.volume, bar.ts_event, bar.ts_init);
queries.add_bar(&pool, &standard_bar).await?;
Defensive patterns

Strategy: validation

Validate before calling

if bar.bar_type.is_composite() {
    // standardize before persisting
    let standard_bar = Bar::new(
        bar.bar_type.standardize(), bar.open, bar.high, bar.low,
        bar.close, bar.volume, bar.ts_event, bar.ts_init,
    );
}

Type guard

fn is_standard_bar(bar: &Bar) -> bool { !bar.bar_type.is_composite() }

Try / catch

match queries::add_bar(&pool, &bar).await {
    Err(e) if e.to_string().contains("composite bar type") => {
        let std_bar = standardize_bar(&bar);
        queries::add_bar(&pool, &std_bar).await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `BarQueries::add_bar(pool, &bar)` with a bar produced from a composite BarType (e.g. an aggregated/transformed bar such as renko/volume-derived bars, or a bar type with a non-standard composition) instead of a standard bar type.

Common situations: Persisting results of a composite aggregation pipeline directly; passing bars received from transformed subscriptions (e.g. `BarType::from_str("...-renko-...")`) straight into the cache write; forgetting `standardize()` when bridging live data into storage.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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