nautechsystems/nautilus_trader · error
Unsupported time in force: {tif:?}
Error message
Unsupported time in force: {tif:?} What it means
When building a Bybit batch order entry, map_time_in_force() translates the Nautilus TimeInForce into Bybit's timeInForce enum for the resolved order type. If the combination is not supported, the mapper returns Err(tif) and the caller wraps it as 'Unsupported time in force: {tif:?}'. Bybit only accepts a subset (GTC, IOC, FOK, PostOnly depending on order type/market), so combos like FOK with post_only or unusual TIFs on conditional orders fail here before any request is sent.
Source
Thrown at crates/adapters/bybit/src/http/client.rs:2536
let instrument = self.instrument_from_cache(&instrument_id.symbol)?;
let bybit_symbol = BybitSymbol::new(instrument_id.symbol.as_str())?;
let bybit_side = match order_side {
OrderSide::Buy => BybitOrderSide::Buy,
OrderSide::Sell => BybitOrderSide::Sell,
};
// For stop/conditional orders, Bybit uses Market/Limit with trigger parameters
let (bybit_order_type, is_stop_order) = match order_type {
OrderType::Market => (BybitOrderType::Market, false),
OrderType::Limit => (BybitOrderType::Limit, false),
OrderType::StopMarket | OrderType::MarketIfTouched => (BybitOrderType::Market, true),
OrderType::StopLimit | OrderType::LimitIfTouched => (BybitOrderType::Limit, true),
_ => anyhow::bail!("Unsupported order type: {order_type:?}"),
};
let bybit_tif = map_time_in_force(bybit_order_type, time_in_force, post_only)
.map_err(|tif| anyhow::anyhow!("Unsupported time in force: {tif:?}"))?;
let market_unit = spot_market_unit(product_type, bybit_order_type, is_quote_quantity);
let trigger_dir = trigger_direction(order_type, order_side, is_stop_order);
let mut order_entry = BybitBatchPlaceOrderEntryBuilder::default();
order_entry.symbol(bybit_symbol.raw_symbol().to_string());
order_entry.side(bybit_side);
order_entry.order_type(bybit_order_type);
order_entry.qty(quantity.to_string());
order_entry.time_in_force(bybit_tif);
order_entry.order_link_id(client_order_id.to_string());
order_entry.market_unit(market_unit);
order_entry.trigger_direction(trigger_dir);
if bbo_side_type.is_none()
&& let Some(price) = price
{
order_entry.price(Some(price.to_string()));
}View on GitHub (pinned to 18893faf8b)
Solutions
- Use a supported TimeInForce for Bybit: Gtc, Ioc, Fok, or post_only Gtc (PostOnly)
- Remove post_only when using IOC/FOK, or set TIF to Gtc for post-only limit orders
- Validate time_in_force at the strategy/config layer before submitting to the client
- For order types that only support GTC (some conditional orders), drop the TIF field
Example fix
// before let order = OrderRequestBuilder::new().order_type(Limit).time_in_force(Gtd, Some(expiry)).post_only(true).build(); // after let order = OrderRequestBuilder::new().order_type(Limit).time_in_force(Gtc, None).post_only(true).build();
Defensive patterns
Strategy: validation
Validate before calling
fn tif_supported_bybit(tif: TimeInForce, post_only: bool) -> bool {
match tif {
TimeInForce::Gtc | TimeInForce::Ioc | TimeInForce::Fok => !post_only || tif == TimeInForce::Gtc,
_ => false,
}
} Type guard
fn is_bybit_tif(tif: TimeInForce) -> Option<&'static str> {
match tif {
TimeInForce::Gtc => Some("GTC"),
TimeInForce::Ioc => Some("IOC"),
TimeInForce::Fok => Some("FOK"),
_ => None,
}
} Try / catch
let resp = client.batch_place_orders(orders).await
.map_err(|e| if e.to_string().contains("Unsupported time in force") {
anyhow::anyhow!("strategy emitted a TIF Bybit does not accept: {e}")
} else { e })?; Prevention
- Restrict strategy configs to GTC/IOC/FOK for Bybit
- Never combine post_only with IOC/FOK
- Validate order params (TIF, type, post_only) before submission
When it happens
Trigger: Placing a batch order with a TimeInForce that doesn't map for the chosen BybitOrderType (e.g. Gtd/Day TIFs, FOK+post_only, unsupported TIF on Market orders); strategies setting time_in_force fields copied from another venue's semantics.
Common situations: Porting strategies from exchanges that support DAY or more granular TIFs to Bybit; misconfigured post_only orders where post_only conflicts with the requested TIF; batch order builders that pass TIF through unvalidated.
Related errors
- Unsupported TIF {time_in_force} for LIMIT on Coinbase
- post-only Derive orders only support GTC time in force; rece
- Execution PostOnly not supported for {order_type:?}
- Failed to query order {}: {}
- {FAILED}: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/feb00427dab946b0.
Report an issue: GitHub.