nautechsystems/nautilus_trader · error · anyhow::Error
Persisted swap intent has no instrument ID
Error message
Persisted swap intent has no instrument ID
What it means
restore_swap_plan (crates/adapters/blockchain/src/execution/client.rs:838) parses the persisted swap intent's instrument_id column; a NULL value aborts reconciliation. The instrument id (e.g. WETH-USDT-3000.UNISWAP_V3) is required to resolve the pool and validate the restored order against the intent. Swap intents are always persisted with it, so NULL means the durable row is incomplete - legacy schema data, manual edits, or a torn write - and the client fails closed instead of reconciling against unknown markets.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:838
.client_order_id
.as_deref()
.ok_or_else(|| anyhow::anyhow!("Persisted swap intent has no client order ID"))?,
)?;
let order = self
.core
.cache()
.try_order_owned(&client_order_id)
.with_context(|| {
format!(
"Cannot reconcile swap intent {} because order {client_order_id} is not restored",
intent.id
)
})?;
let instrument_id = InstrumentId::from_str(
intent
.instrument_id
.as_deref()
.ok_or_else(|| anyhow::anyhow!("Persisted swap intent has no instrument ID"))?,
)?;
anyhow::ensure!(
order.instrument_id() == instrument_id,
"Persisted swap instrument {instrument_id} does not match restored order instrument {}",
order.instrument_id()
);
anyhow::ensure!(
intent.trader_id.as_deref() == Some(order.trader_id().as_str()),
"Persisted swap trader does not match restored order"
);
anyhow::ensure!(
intent.strategy_id.as_deref() == Some(order.strategy_id().as_str()),
"Persisted swap strategy does not match restored order"
);
anyhow::ensure!(
intent.account_id.as_deref() == Some(self.core.account_id.as_str()),
"Persisted swap account does not match execution client account"
);View on GitHub (pinned to 2114cf6f76)
Solutions
- Inspect the intent row and its transaction hashes: SELECT id, status, instrument_id FROM execution_intent WHERE id = <id>.
- Confirm the transaction's on-chain outcome, then mark the intent resolved or remove it so reconciliation proceeds.
- Re-run the deployment that writes instrument_id on every swap intent (current EXECUTION_SCHEMA_VERSION).
- Audit for other NULL columns in the same row (client_order_id, trader_id, pool_address, amount_in) - they fail subsequent checks too.
Defensive patterns
Strategy: try-catch
Validate before calling
-- Pre-flight: active swap intents missing required identity columns
SELECT id, status
FROM execution_intent
WHERE status IN ('prepared', 'signed', 'submitted')
AND purpose = 'swap'
AND instrument_id IS NULL; Type guard
fn is_missing_instrument_id(e: &anyhow::Error) -> bool {
e.to_string().contains("Persisted swap intent has no instrument ID")
} Try / catch
if let Err(e) = client.connect().await {
if is_missing_instrument_id(&e) {
// incomplete durable row: stop and repair the intent record before trading
log::error!("cannot reconcile swap intent without instrument: {e}");
}
return Err(e);
} Prevention
- Audit active intents for NULL identity columns before every version upgrade.
- Reject database restores that carry intents from older schemas into a live deployment.
- Ensure swap submission paths always persist instrument_id alongside the intent.
When it happens
Trigger: An active swap intent row with NULL instrument_id encountered at connect()-time reconciliation; intent rows migrated from an older schema that lacked the column values; direct SQL manipulation of the intent table.
Common situations: Restoring a database backup taken with an older crate version; bulk-editing or ETL scripts that null out 'optional-looking' columns.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Persisted swap intent has no client order ID
- Persisted swap instrument {instrument_id} does not match res
- Persisted swap intent has no pool address
- Persisted swap intent has no input amount
- Execution transaction hash {transaction_hash} was not found
AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21).
Data as JSON: /api/errors/5d0d32a378577271.
Report an issue: GitHub.