{"record":{"id":"d5f1be825f654eea","repo":"nautechsystems/nautilus_trader","slug":"persisted-swap-intent-has-no-input-amount","errorCode":null,"errorMessage":"Persisted swap intent has no input amount","messagePattern":"Persisted swap intent has no input amount","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":874,"sourceCode":"        );\n\n        let pool = self.resolve_pool(&instrument_id)?;\n        let pool_address = Address::from_str(\n            intent\n                .pool_address\n                .as_deref()\n                .ok_or_else(|| anyhow::anyhow!(\"Persisted swap intent has no pool address\"))?,\n        )?;\n        anyhow::ensure!(\n            pool.address == pool_address,\n            \"Persisted pool {pool_address} does not match restored pool {}\",\n            pool.address\n        );\n        let amount_in = U256::from_str(\n            intent\n                .amount_in\n                .as_deref()\n                .ok_or_else(|| anyhow::anyhow!(\"Persisted swap intent has no input amount\"))?,\n        )?;\n        let fee = U24::try_from(\n            pool.fee\n                .ok_or_else(|| anyhow::anyhow!(\"Restored pool {instrument_id} has no fee\"))?,\n        )?;\n        let quote_token = pool.get_quote_token();\n        let quote_currency = Currency::new_checked(\n            &quote_token.symbol,\n            quote_token.decimals,\n            0,\n            &quote_token.name,\n            CurrencyType::Crypto,\n        )?;\n        let token_in = pool.get_base_token().address;\n        let token_out = quote_token.address;\n\n        Ok(SwapPlan {\n            order,","sourceCodeStart":856,"sourceCodeEnd":892,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/execution/client.rs#L856-L892","documentation":"restore_swap_plan (crates/adapters/blockchain/src/execution/client.rs:874) parses the persisted swap intent's amount_in column as U256; a NULL value aborts reconciliation. The input amount is required to reconstruct the SwapPlan (it feeds min_amount_out checks and emitted fill quantities) and swap intents always persist it, so NULL indicates incomplete durable state - a legacy row, torn write, or manual edit - rather than any valid record.","triggerScenarios":"An active swap intent row with NULL amount_in hit during connect()-time reconciliation; rows written by an older writer that did not persist the amount; direct SQL manipulation.","commonSituations":"Restoring backups across versions; ETL scripts that dropped 'unused' columns; partial writes during a database outage.","solutions":["Inspect the intent row: SELECT id, status, amount_in FROM execution_intent WHERE id = <id>.","Verify the on-chain swap outcome via the intent's transaction hash, then mark the intent resolved so restarts stop failing.","Ensure the deployment writing intents is current so amount_in is always persisted.","Backfill amount_in from on-chain swap event data if you need history intact."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"-- Pre-flight: active swap intents missing the input amount\nSELECT id, status\nFROM execution_intent\nWHERE status IN ('prepared', 'signed', 'submitted')\n  AND purpose = 'swap'\n  AND amount_in IS NULL;","typeGuard":"fn is_missing_amount_in(e: &anyhow::Error) -> bool {\n    e.to_string().contains(\"Persisted swap intent has no input amount\")\n}","tryCatchPattern":"if let Err(e) = client.connect().await {\n    if is_missing_amount_in(&e) {\n        // incomplete durable row: backfill from the on-chain swap event or resolve the intent\n        log::error!(\"swap intent lacks amount_in: {e}\");\n    }\n    return Err(e);\n}","preventionTips":["Audit active intents for NULL economic columns before version upgrades.","Backfill amount_in from on-chain Swap events if historical accuracy matters.","Keep the intent writer on the current schema so amounts are always persisted."],"tags":["reconciliation","postgres","amount-in","data-integrity","rust"],"backgroundTag":"missing-required-field","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}