{"record":{"id":"7996aff7fda17e22","repo":"nautechsystems/nautilus_trader","slug":"cannot-persist-bar-with-composite-bar-type-the","errorCode":null,"errorMessage":"Cannot persist bar with composite bar type {}: the bar table stores only the standard form; standardize the bar type before persisting","messagePattern":"Cannot persist bar with composite bar type (.+?): the bar table stores only the standard form; standardize the bar type before persisting","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/infrastructure/src/sql/queries.rs","lineNumber":1342,"sourceCode":"    ) -> anyhow::Result<Vec<QuoteTick>> {\n        sqlx::query_as::<_, QuoteTickRow>(\n            r#\"SELECT * FROM \"quote\" WHERE instrument_id = $1 ORDER BY ts_event ASC\"#,\n        )\n        .bind(instrument_id.to_string())\n        .fetch_all(pool)\n        .await\n        .map(|rows| rows.into_iter().map(|row| row.0).collect())\n        .map_err(|e| anyhow::anyhow!(\"Failed to load quotes: {e}\"))\n    }\n\n    /// Inserts a `Bar` entry via the provided `pool`.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the SQL INSERT operation fails.\n    pub async fn add_bar(pool: &PgPool, bar: &Bar) -> anyhow::Result<()> {\n        if bar.bar_type.is_composite() {\n            anyhow::bail!(\n                \"Cannot persist bar with composite bar type {}: the bar table stores only \\\n                 the standard form; standardize the bar type before persisting\",\n                bar.bar_type,\n            );\n        }\n\n        let bar_step = i32::try_from(bar.bar_type.spec().step.get())\n            .map_err(|e| anyhow::anyhow!(\"invalid bar step: {e}\"))?;\n\n        sqlx::query(r#\"\n            INSERT INTO \"bar\" (\n                instrument_id, step, bar_aggregation, price_type, aggregation_source, open, high, low, close, volume, ts_event, ts_init, created_at, updated_at\n            ) VALUES (\n                $1, $2, $3::bar_aggregation, $4::price_type, $5::aggregation_source, $6, $7, $8, $9, $10, $11, $12, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP\n            )\n            ON CONFLICT (id)\n            DO UPDATE\n            SET","sourceCodeStart":1324,"sourceCodeEnd":1360,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/infrastructure/src/sql/queries.rs#L1324-L1360","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call `bar.bar_type.standardize()` (build the bar from the standardized bar type) before persisting.","Persist only bars with standard bar types; keep composite bars in memory or a separate store if needed.","Filter composite bars out at the subscription/handler level before writing to the SQL cache."],"exampleFix":"// before\nqueries.add_bar(&pool, &bar).await?;\n\n// after\nlet standard_bar = Bar::new(bar.bar_type.standardize(), bar.open, bar.high, bar.low, bar.close, bar.volume, bar.ts_event, bar.ts_init);\nqueries.add_bar(&pool, &standard_bar).await?;","handlingStrategy":"validation","validationCode":"if bar.bar_type.is_composite() {\n    // standardize before persisting\n    let standard_bar = Bar::new(\n        bar.bar_type.standardize(), bar.open, bar.high, bar.low,\n        bar.close, bar.volume, bar.ts_event, bar.ts_init,\n    );\n}","typeGuard":"fn is_standard_bar(bar: &Bar) -> bool { !bar.bar_type.is_composite() }","tryCatchPattern":"match queries::add_bar(&pool, &bar).await {\n    Err(e) if e.to_string().contains(\"composite bar type\") => {\n        let std_bar = standardize_bar(&bar);\n        queries::add_bar(&pool, &std_bar).await?;\n    }\n    other => other?,\n}","preventionTips":["Always standardize bar types before any SQL cache write.","Filter composite bars at the data-handler level.","Keep composite aggregation outputs in a dedicated in-memory store, not the bar table."],"tags":["database","validation","bars","rust"],"backgroundTag":"invalid-argument-value","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"}