nautechsystems/nautilus_trader · error · anyhow::Error
Failed to reconstruct migrated hash: {e}
Error message
Failed to reconstruct migrated hash: {e} What it means
This error wraps sqlx failures from the UPDATE of execution_transaction_hash that reconstructs a migrated terminal transaction hash (status, block number/hash, receipt_success, gas_used, effective_gas_price). It fires only when the UPDATE statement errors at the database level; the separate 'Migrated terminal transaction hash was not found' error covers the zero-rows-affected case. The driver error is interpolated as {e}.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:4273
UPDATE execution_transaction_hash
SET status = $3, block_number = $4, block_hash = $5,
receipt_success = $6, gas_used = $7,
effective_gas_price = $8, updated_at = NOW()
WHERE intent_id = $1 AND transaction_hash = $2 AND current
AND payload_expected
",
)
.bind(record.intent_id)
.bind(transaction_hash)
.bind(status.as_str())
.bind(block_number)
.bind(block_hash)
.bind(receipt_success)
.bind(gas_used)
.bind(record.effective_gas_price.as_deref())
.execute(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to reconstruct migrated hash: {e}"))?;
anyhow::ensure!(
hash_result.rows_affected() == 1,
"Migrated terminal transaction hash was not found"
);
sqlx::query(
"UPDATE execution_intent SET status = $2, updated_at = NOW() WHERE id = $1",
)
.bind(record.intent_id)
.bind(status.as_str())
.execute(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to reconstruct migrated intent: {e}"))?;
if current_status != status.as_str() {
sqlx::query(
"
INSERT INTO execution_transaction_transition (
intent_id, transaction_hash_id, transition_key,
from_status, to_status, block_number, block_hashView on GitHub (pinned to 18893faf8b)
Solutions
- Read the interpolated {e} to identify the failing column or constraint and fix the offending migration record field.
- Verify the target schema matches the migration's expectations (execution_transaction_hash columns: status, block_number, block_hash, receipt_success, gas_used, effective_gas_price).
- Confirm numeric fields fit their column types (BIGINT bounds for block_number/gas_used) and price strings parse as NUMERIC before migrating.
- Re-run the migration if the error was transient (connection drop); the transaction rollback preserves consistency.
- Check the DB server logs at the failure time for constraint or serialization details.
Example fix
// before: binding unvalidated values
.bind(record.effective_gas_price.as_deref())
// after: validate before executing
let price = record.effective_gas_price.as_deref()
.map(|p| p.parse::<rust_decimal::Decimal>())
.transpose()
.context("invalid effective_gas_price in migration record")?;
.bind(price) Defensive patterns
Strategy: validation
Validate before calling
// before migrating, confirm the hash row is updatable and values fit columns
let row = sqlx::query_scalar::<_, i64>(
"SELECT COUNT(*) FROM execution_transaction_hash \
WHERE intent_id = $1 AND transaction_hash = $2 AND current AND payload_expected",
).bind(&record.intent_id).bind(&record.transaction_hash)
.fetch_one(&pool).await?;
anyhow::ensure!(row == 1, "hash row not updatable for intent {}", record.intent_id); Type guard
fn hash_fields_in_range(record: &MigrationRecord) -> bool {
record.block_number.map_or(false, |b| i64::try_from(b).is_ok())
&& record.gas_used.map_or(false, |g| i64::try_from(g).is_ok())
&& record.effective_gas_price.as_deref().map_or(true, |p| p.parse::<rust_decimal::Decimal>().is_ok())
} Try / catch
if let Err(e) = run_migration(&pool, records).await {
let msg = format!("{e:#}");
if msg.contains("Failed to reconstruct migrated hash") {
tracing::error!("hash UPDATE failed at DB level, check schema/constraints: {msg}");
}
return Err(e); // transaction rolled back; state consistent
} Prevention
- Keep target schema migrations in sync with the code version before running data migrations.
- Validate numeric fields fit BIGINT and price strings parse as NUMERIC before migrating.
- Normalize transaction hashes (lowercase hex) in evidence and DB.
- Run data migrations in a maintenance window with no concurrent DDL.
When it happens
Trigger: The UPDATE `... WHERE intent_id = $1 AND transaction_hash = $2 AND current AND payload_expected` fails due to: type/column mismatches (e.g. effective_gas_price string not castable to the target NUMERIC column), i64 out-of-range values for block_number/gas_used, CHECK/FK constraint violations, a lost DB connection mid-transaction, or concurrent DDL/schema drift.
Common situations: Migration evidence whose effective_gas_price does not parse into the target column; block numbers or gas values exceeding column range; migration run against a database whose schema predates a required column; connection timeouts during a long-running migration batch.
Related errors
- Failed to reconstruct migrated intent: {e}
- Failed to lock migrated intent: {e}
- Failed to persist migration evidence: {e}
- Failed to seed chain table: {e}
- Failed to call create_block_partition for chain {}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/05fd4a08070ec4d1.
Report an issue: GitHub.