nautechsystems/nautilus_trader · error
Restored transaction purpose is inconsistent
Error message
Restored transaction purpose is inconsistent
What it means
After a restored transaction finalizes, the client maps the (restored swap plan, purpose) pair to a trace purpose string ('swap_sell', 'swap_buy', 'wrap', 'approve') for finality verification. This bail fires when the combination matches none of the valid shapes — e.g. a Swap purpose with no restored plan, or a Wrap/Approve purpose with a plan — signalling corrupted or inconsistent persisted reconciliation state.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:1388
if intent.status == "finalized" {
InclusionOutcome::Finalized(included)
} else {
InclusionOutcome::Reverted(included)
}
} else {
executor.await_finality(&prepared).await?
};
match outcome {
InclusionOutcome::Finalized(mut included) => {
let trace_purpose = match (&plan, purpose) {
(Some(plan), TransactionPurpose::Swap) => match plan.order.order_side() {
OrderSide::Sell => "swap_sell",
OrderSide::Buy => "swap_buy",
},
(None, TransactionPurpose::Wrap) => "wrap",
(None, TransactionPurpose::Approve) => "approve",
_ => anyhow::bail!("Restored transaction purpose is inconsistent"),
};
included.finality.decisions.extend(
verify_finalized_transaction(
&included,
&intent,
nonce,
&prepared.raw_tx,
&executor,
trace_purpose,
)
.await?,
);
if let Some(plan) = plan {
let fill = validate_finalized_swap_fill(&plan, &included)?;
let wallet =
load_verified_wallet_after_fill(&plan, &included, &executor).await?;
if !finality_already_committed {View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the execution database rows for the failing intent: confirm the purpose field and whether a swap plan row exists; they must agree (Swap ⇔ plan present, Wrap/Approve ⇔ no plan).
- Re-run or repair the swap plan persistence so restore_swap_plan() returns the plan for Swap-purposed intents.
- Check for a version mismatch between the code that wrote the intent and the code restoring it; upgrade/migrate the database schema to the current version.
- Restore the affected intent rows from a consistent backup if the state is corrupted.
Defensive patterns
Strategy: validation
Validate before calling
// Verify purpose/plan consistency before reconnecting
fn purpose_plan_consistent(purpose: &TransactionPurpose, plan: &Option<SwapPlan>) -> bool {
match purpose {
TransactionPurpose::Swap => plan.is_some(),
_ => plan.is_none(),
}
} Type guard
fn restore_shape_is_valid(purpose: &TransactionPurpose, plan: &Option<SwapPlan>) -> bool {
matches!((plan, purpose),
(Some(_), TransactionPurpose::Swap)
| (None, TransactionPurpose::Wrap)
| (None, TransactionPurpose::Approve))
} Try / catch
match client.connect().await {
Err(e) if e.to_string().contains("purpose is inconsistent") => {
log::error!("corrupt persisted reconciliation state: {e}");
// halt connect; repair DB rows or restore from backup
}
result => result?,
} Prevention
- Persist the intent and its swap plan atomically in one transaction so they can never disagree.
- Run database schema migrations in lockstep with client upgrades.
- Never hand-edit execution database rows; use the provided recovery tooling.
When it happens
Trigger: connect() → reconcile_unresolved_execution() on a finalized intent where the persisted purpose and the restored plan disagree: purpose == Swap but restore_swap_plan returned no plan, or purpose == Wrap/Approve while a swap plan exists for the intent.
Common situations: Database rows for the intent and its swap plan written by different versions of the software; a swap plan that failed to persist while the intent recorded Swap purpose; manual database edits or partial restores; restore logic returning None for a plan that should exist.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Finalized execution transaction {tx_hash} no longer has a re
- Finalized block {} changed from {} to {} before intent valid
- Finalized transaction {} emitted {} Swap logs; expected exac
- Execution schema version {} is newer than supported version
- Verified finalized transaction count advanced without an act
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/42e19d321e6d4c86.
Report an issue: GitHub.