{"record":{"id":"8109aed577c019fe","repo":"nautechsystems/nautilus_trader","slug":"reduce-only-requires-spot-account-type-margin-cur","errorCode":null,"errorMessage":"reduce_only requires spot_account_type=Margin (current: Cash)","messagePattern":"reduce_only requires spot_account_type=Margin \\(current: Cash\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/kraken/src/http/spot/client.rs","lineNumber":3174,"sourceCode":"                OrderSide::Buy => \"buy\",\n                _ => \"sell\",\n            };\n\n            if valid_tiers.is_empty() {\n                anyhow::bail!(\"Leverage not supported for {raw_symbol} on {side_label} side\");\n            }\n\n            if !valid_tiers.contains(&(n as i32)) {\n                anyhow::bail!(\n                    \"Leverage {n}:1 not supported for {raw_symbol} on {side_label} side (valid: {valid_tiers:?})\"\n                );\n            }\n            builder.leverage(format!(\"{n}:1\"));\n        }\n\n        if reduce_only {\n            if account_type != AccountType::Margin {\n                anyhow::bail!(\"reduce_only requires spot_account_type=Margin (current: Cash)\");\n            }\n            builder.reduce_only(true);\n        }\n\n        builder\n            .build()\n            .map_err(|e| anyhow::anyhow!(\"Failed to build order params: {e}\"))\n    }\n}\n\nfn collect_spot_statuses(\n    asset_pairs: &AssetPairsResponse,\n) -> AHashMap<InstrumentId, MarketStatusAction> {\n    asset_pairs\n        .iter()\n        .map(|(_, definition)| {\n            let symbol_str = definition.wsname.as_ref().unwrap_or(&definition.altname);\n            let normalized_symbol = normalize_spot_symbol(symbol_str.as_str());","sourceCodeStart":3156,"sourceCodeEnd":3192,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/kraken/src/http/spot/client.rs#L3156-L3192","documentation":"reduce_only is a margin/leverage concept — it closes existing leveraged exposure and has no meaning for a Cash spot account. The adapter rejects reduce_only=true on Cash accounts before sending an order Kraken would refuse.","triggerScenarios":"Submitting a Kraken Spot order with reduce_only = true while the client's account_type is AccountType::Cash; typical when a position-exit signal path always sets reduce_only regardless of venue/account configuration.","commonSituations":"Sharing exit-order logic between futures and spot; account switched from Margin to Cash while strategy state still flags exits as reduce-only.","solutions":["Set reduce_only = false (or omit it) for cash-account orders.","Reconfigure the client with spot_account_type = AccountType::Margin if the orders genuinely reduce margin positions.","Gate reduce_only on account type in strategy code so it is only set when trading a margin account."],"exampleFix":"// before\nreduce_only: true, // account_type: AccountType::Cash\n// after\nreduce_only: false","handlingStrategy":"validation","validationCode":"let reduce_only = reduce_only && account_config.spot_account_type == AccountType::Margin;","typeGuard":null,"tryCatchPattern":"if let Err(e) = client.submit_order(req) {\n    if e.to_string().contains(\"reduce_only requires spot_account_type=Margin\") {\n        // resubmit with reduce_only=false or switch to a margin client\n    }\n}","preventionTips":["Set reduce_only only in margin-position exit code paths.","Derive reduce_only from account type rather than hard-coding it.","Add a config-time assertion pairing reduce_only intent with account type."],"tags":["kraken","spot","reduce-only","margin","configuration"],"backgroundTag":"invalid-config-value","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"}