nautechsystems/nautilus_trader · error · anyhow::Error

Failed to insert into custom table: {e}

Error message

Failed to insert into custom table: {e}

What it means

Raised by `add_custom_data` when the INSERT into the `custom` table fails. All JSON extraction steps succeeded; the error comes from sqlx executing the INSERT against PostgreSQL, wrapped with this message via anyhow.

Source

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

                updated_at = CURRENT_TIMESTAMP
        "#,
        )
        .bind(data_type_name)
        .bind(&metadata_json)
        .bind(identifier)
        .bind(&value_json)
        .bind(
            value_json
                .get("ts_event")
                .and_then(serde_json::Value::as_u64)
                .unwrap_or_else(|| data.ts_init().as_u64())
                .to_string(),
        )
        .bind(data.ts_init().to_string())
        .execute(pool)
        .await
        .map(|_| ())
        .map_err(|e| anyhow::anyhow!("Failed to insert into custom table: {e}"))
    }

    /// Loads all `CustomData` entries of `data_type` via the provided `pool`.
    ///
    /// Filters by `data_type`, `metadata`, and `identifier` columns to match the requested data type.
    ///
    /// # Errors
    ///
    /// Returns an error if the SQL SELECT or deserialization fails.
    pub async fn load_custom_data(
        pool: &PgPool,
        data_type: &DataType,
    ) -> anyhow::Result<Vec<CustomData>> {
        let metadata_json = data_type.metadata().as_ref().map_or(
            Ok(serde_json::Value::Object(serde_json::Map::new())),
            serde_json::to_value,
        )?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the embedded sqlx error to find the exact DB-level cause.
  2. Apply the latest migrations so the `custom` table has all expected columns.
  3. Verify identifier/uniqueness constraints aren't violated by the data_type/identifier combination.
  4. Check database writability and pool health.
Defensive patterns

Strategy: try-catch

Validate before calling

let exists: bool = sqlx::query_scalar(
    "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'custom')")
    .fetch_one(pool).await?;
anyhow::ensure!(exists, "custom table missing; run migrations");

Try / catch

if let Err(e) = add_custom_data(&pool, &data).await {
    tracing::error!("custom insert failed: {e:#}");
    return Err(e.context("custom data persistence failed"));
}

Prevention

When it happens

Trigger: Calling `add_custom_data(pool, data)` when the `custom` table doesn't exist, columns mismatch (e.g., missing data_type/metadata/identifier columns), a constraint or type check fails on the JSONB value, or the connection dies during execute.

Common situations: Schema migrations not applied or out of date; inserting a data type whose identifier column value violates a unique constraint; read-only database; pool connection closed.

Related errors


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