{"record":{"id":"d2addbe67b635d43","repo":"nautechsystems/nautilus_trader","slug":"failed-to-insert-into-currency-table-e","errorCode":null,"errorMessage":"Failed to insert into currency table: {e}","messagePattern":"Failed to insert into currency table: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/infrastructure/src/sql/queries.rs","lineNumber":115,"sourceCode":"\n    /// Inserts or ignores a `Currency` row via the provided `pool`.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the INSERT operation fails.\n    pub async fn add_currency(pool: &PgPool, currency: Currency) -> anyhow::Result<()> {\n        sqlx::query(\n            \"INSERT INTO currency (id, precision, iso4217, name, currency_type) VALUES ($1, $2, $3, $4, $5::currency_type) ON CONFLICT (id) DO NOTHING\"\n        )\n            .bind(currency.code.as_str())\n            .bind(i32::from(currency.precision))\n            .bind(i32::from(currency.iso4217))\n            .bind(currency.name.as_str())\n            .bind(CurrencyTypePg(currency.currency_type))\n            .execute(pool)\n            .await\n            .map(|_| ())\n            .map_err(|e| anyhow::anyhow!(\"Failed to insert into currency table: {e}\"))\n    }\n\n    /// Loads all `Currency` entries via the provided `pool`.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the SELECT operation fails.\n    pub async fn load_currencies(pool: &PgPool) -> anyhow::Result<Vec<Currency>> {\n        sqlx::query_as::<_, CurrencyRow>(\"SELECT * FROM currency ORDER BY id ASC\")\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 currencies: {e}\"))\n    }\n\n    /// Loads a single `Currency` entry by `code` via the provided `pool`.\n    ///\n    /// # Errors","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/infrastructure/src/sql/queries.rs#L97-L133","documentation":"`DatabaseQueries::add_currency` inserts a `Currency` row with `ON CONFLICT (id) DO NOTHING` (duplicate ids are silently ignored, never errors) and wraps any other sqlx failure in this anyhow error. Common causes are a missing `currency` table, connection failure, or — most often — an invalid value for the Postgres `currency_type` enum cast because the database enum is outdated relative to the binary.","triggerScenarios":"Calling `DatabaseQueries::add_currency(pool, currency)` when: migrations weren't applied (table or `currency_type` enum type missing); `currency.currency_type` can't be cast to the DB enum (newer CurrencyType variant not in the DB); precision/iso4217 violate column constraints; connection drops.","commonSituations":"Version skew where code emits a new currency_type the database enum lacks; fresh database without migrations; restricted DB role without INSERT privilege.","solutions":["Run migrations so the `currency` table and `currency_type` enum include all variants used by this code version.","If the inner error says 'invalid input value for enum currency_type', update the DB enum (ALTER TYPE ... ADD VALUE) or upgrade the code.","Verify connectivity and INSERT privileges on `currency`.","Remember duplicates are ignored by design; a raised error indicates a real failure, not a duplicate id."],"exampleFix":"-- before: stale DB enum\n-- after: add the missing variant\nALTER TYPE currency_type ADD VALUE IF NOT EXISTS 'crypto';","handlingStrategy":"try-catch","validationCode":"let known: Vec<String> = sqlx::query_scalar(\n    \"SELECT enumlabel FROM pg_enum e JOIN pg_type t ON e.enumtypid = t.oid WHERE t.typname = 'currency_type'\",\n).fetch_all(pool).await?;\n// ensure every CurrencyType variant this binary can emit is representable in the DB enum","typeGuard":null,"tryCatchPattern":"if let Err(e) = DatabaseQueries::add_currency(&pool, currency).await {\n    if e.to_string().contains(\"invalid input value for enum\") {\n        return Err(anyhow::anyhow!(\n            \"DB currency_type enum outdated vs binary — run migrations/upgrade: {e}\"\n        ));\n    }\n    return Err(e);\n}","preventionTips":["Keep database schema/enum migrations in lock-step with the application version.","Rely on the query's ON CONFLICT DO NOTHING for idempotency; any raised error is a real failure, not a duplicate id.","Test currency persistence against a freshly migrated database in CI.","Use a role with INSERT privileges on the `currency` table."],"tags":["postgres","sqlx","database","insert","currency","enum"],"backgroundTag":"database-write-failed","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"}