nautechsystems/nautilus_trader · error
FOK time in force only supported for LIMIT orders on Kraken
Error message
FOK time in force only supported for LIMIT orders on Kraken Spot
What it means
Kraken Spot only honors FOK (fill-or-kill) time in force on LIMIT orders. The client validates the combination and bails if TimeInForce::Fok is paired with any non-Limit order type (market, stop, trailing, etc.), since the venue would reject it.
Source
Thrown at crates/adapters/kraken/src/http/spot/client.rs:3042
OrderType::StopLimit => KrakenOrderType::StopLossLimit,
OrderType::MarketIfTouched => KrakenOrderType::TakeProfit,
OrderType::LimitIfTouched => KrakenOrderType::TakeProfitLimit,
OrderType::TrailingStopMarket => KrakenOrderType::TrailingStop,
OrderType::TrailingStopLimit => KrakenOrderType::TrailingStopLimit,
_ => anyhow::bail!("Unsupported order type: {order_type:?}"),
};
let mut oflags = Vec::new();
let is_limit_order = matches!(
order_type,
OrderType::Limit
| OrderType::StopLimit
| OrderType::LimitIfTouched
| OrderType::TrailingStopLimit
);
if time_in_force == TimeInForce::Fok && order_type != OrderType::Limit {
anyhow::bail!("FOK time in force only supported for LIMIT orders on Kraken Spot");
}
let (timeinforce, expiretm) =
compute_time_in_force(is_limit_order, time_in_force, expire_time)?;
if post_only {
oflags.push(KRAKEN_OFLAG_POST_ONLY);
}
if quote_quantity {
oflags.push(KRAKEN_OFLAG_QUOTE_QUANTITY);
}
let mut builder = KrakenSpotAddOrderParamsBuilder::default();
builder
.cl_ord_id(truncate_cl_ord_id(&client_order_id))
.broker(NAUTILUS_KRAKEN_BROKER_ID)
.pair(raw_symbol)View on GitHub (pinned to 18893faf8b)
Solutions
- Use OrderType::Limit when TimeInForce::Fok is required.
- For market orders use TimeInForce::Gtc (or the venue's supported TIF) instead of FOK.
- Validate order_type/time_in_force combinations in strategy config before submission.
Example fix
// before let order = order_factory.market(instrument_id, side, qty, TimeInForce::Fok, ...); // after let order = order_factory.market(instrument_id, side, qty, TimeInForce::Gtc, ...);
Defensive patterns
Strategy: validation
Validate before calling
if time_in_force == TimeInForce::Fok && order_type != OrderType::Limit {
return Err("FOK requires OrderType::Limit on Kraken Spot");
} Type guard
fn fok_is_valid(tif: &TimeInForce, ot: &OrderType) -> bool {
*tif != TimeInForce::Fok || *ot == OrderType::Limit
} Try / catch
match client.submit_order(order).await {
Err(e) if e.to_string().contains("FOK time in force only supported") => {
log::error!("resubmit as LIMIT or switch TIF to GTC");
}
Err(e) => return Err(e),
Ok(r) => r,
} Prevention
- Pair FOK only with LIMIT orders in strategy configuration
- Default market orders to GTC on Kraken Spot
- Validate order_type/TIF combinations in a pre-trade config check
When it happens
Trigger: Submitting a MARKET, STOP_MARKET, TRAILING_STOP_MARKET (or any non-LIMIT) order with time_in_force = TimeInForce::Fok.
Common situations: Strategies that uniformly set FOK on all orders; ported code from venues where FOK applies to market orders; configuration-driven TIF applied without regard to order type.
Related errors
- unsupported time in force for Derive: {other:?}
- Unsupported order type: {order_type:?}
- Unsupported time in force: {time_in_force:?}
- Lighter market orders support only TimeInForce::Gtc or TimeI
- GTD STOP_LIMIT requires expire_time
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/463eee459212b8af.
Report an issue: GitHub.