{"record":{"id":"aac913bd7e6e57ed","repo":"nautechsystems/nautilus_trader","slug":"fok-time-in-force-is-not-supported-on-kraken-ws-v2","errorCode":null,"errorMessage":"FOK time in force is not supported on Kraken WS v2; use REST","messagePattern":"FOK time in force is not supported on Kraken WS v2; use REST","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/kraken/src/common/order_params.rs","lineNumber":226,"sourceCode":"            cl_ord_id: Some(vec![truncate_cl_ord_id(&cmd.client_order_id)]),\n        }\n    }\n}\n\npub(crate) fn compute_ws_time_in_force(\n    is_limit_order: bool,\n    time_in_force: TimeInForce,\n    expire_time: Option<UnixNanos>,\n) -> anyhow::Result<Option<KrakenTimeInForce>> {\n    if !is_limit_order {\n        return Ok(None);\n    }\n\n    match time_in_force {\n        TimeInForce::Gtc => Ok(None),\n        TimeInForce::Ioc => Ok(Some(KrakenTimeInForce::ImmediateOrCancel)),\n        TimeInForce::Fok => {\n            anyhow::bail!(\"FOK time in force is not supported on Kraken WS v2; use REST\")\n        }\n        TimeInForce::Gtd => {\n            expire_time.ok_or_else(|| {\n                anyhow::anyhow!(\"GTD time in force requires expire_time parameter\")\n            })?;\n            Ok(Some(KrakenTimeInForce::GoodTilDate))\n        }\n        _ => anyhow::bail!(\"Unsupported time in force: {time_in_force:?}\"),\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use nautilus_core::{UUID4, UnixNanos};\n    use nautilus_model::identifiers::{\n        ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId,\n    };\n    use rstest::rstest;","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/kraken/src/common/order_params.rs#L208-L244","documentation":"compute_ws_time_in_force translates Nautilus TimeInForce to Kraken WS time-in-force values. Kraken's WS v2 addOrder API does not support fill-or-kill, so Fok is explicitly rejected and the caller is directed to the REST API.","triggerScenarios":"Submitting any order with time_in_force = Fok through the Kraken WS path, either via build_add_order_params or build_batch_order.","commonSituations":"Strategy uses FOK for aggressive all-or-nothing entries (common pattern ported from crypto derivatives venues); Kraken Spot WS has no equivalent TIF so it must go through REST or be replaced.","solutions":["Use time-in-force IoC (immediate-or-cancel) instead of Fok if partial fills are acceptable, via the WS path.","Route FOK orders through the Kraken REST execution client.","Configure the strategy's order templates to use Gtc/Ioc for Kraken WS execution."],"exampleFix":"// before\norder_factory.limit(instrument_id, side, qty, price, TimeInForce::Fok, None)\n// after\norder_factory.limit(instrument_id, side, qty, price, TimeInForce::Ioc, None) // FOK unsupported on WS v2","handlingStrategy":"validation","validationCode":"if order.time_in_force() == TimeInForce::Fok {\n    // use REST execution client or switch to TimeInForce::Ioc\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = ws_client.submit(order).await {\n    if e.to_string().contains(\"FOK time in force\") {\n        rest_client.submit(order).await?;\n    } else { return Err(e); }\n}","preventionTips":["Do not configure FOK order templates for Kraken WS execution.","Prefer IOC when partial fills are tolerable, REST when strict FOK is required.","Keep a venue/TIF support matrix in strategy configuration docs."],"tags":["rust","kraken","websocket","time-in-force","unsupported-feature"],"backgroundTag":"operation-not-supported","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}