nautechsystems/nautilus_trader · error · anyhow::Error
GTD time in force requires expire_time parameter
Error message
GTD time in force requires expire_time parameter
What it means
On Kraken WS v2, a GTD (Good-Til-Date) order requires an explicit expire_time; compute_ws_time_in_force bails with this error when TimeInForce::Gtd is requested without one. The library throws it because the Kraken AddOrder message cannot express GTD without an expiry timestamp.
Source
Thrown at crates/adapters/kraken/src/common/order_params.rs:230
pub(crate) fn compute_ws_time_in_force(
is_limit_order: bool,
time_in_force: TimeInForce,
expire_time: Option<UnixNanos>,
) -> anyhow::Result<Option<KrakenTimeInForce>> {
if !is_limit_order {
return Ok(None);
}
match time_in_force {
TimeInForce::Gtc => Ok(None),
TimeInForce::Ioc => Ok(Some(KrakenTimeInForce::ImmediateOrCancel)),
TimeInForce::Fok => {
anyhow::bail!("FOK time in force is not supported on Kraken WS v2; use REST")
}
TimeInForce::Gtd => {
expire_time.ok_or_else(|| {
anyhow::anyhow!("GTD time in force requires expire_time parameter")
})?;
Ok(Some(KrakenTimeInForce::GoodTilDate))
}
_ => anyhow::bail!("Unsupported time in force: {time_in_force:?}"),
}
}
#[cfg(test)]
mod tests {
use nautilus_core::{UUID4, UnixNanos};
use nautilus_model::identifiers::{
ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId,
};
use rstest::rstest;
use rust_decimal_macros::dec;
use super::*;
View on GitHub (pinned to 18893faf8b)
Solutions
- Provide expire_time (as a Unix timestamp) when constructing the order with TimeInForce::Gtd.
- Fall back to Gtc if no expiry is meaningful for the strategy.
- Validate at the strategy/order-builder layer that Gtd orders always carry an expiry before submission.
- Use the REST API instead of WS v2 if the order router cannot supply expire_time.
Example fix
// before
let tif = TimeInForce::Gtd;
build_add_order_params(&order, None)?; // expire_time not passed
// after
let expire_time = order.expire_time.expect("GTD orders require expire_time");
build_add_order_params(&order, Some(expire_time))?; Defensive patterns
Strategy: validation
Validate before calling
// Rust: check before submitting
if order.time_in_force == TimeInForce::Gtd && order.expire_time.is_none() {
return Err(anyhow::anyhow!("order {} is GTD but has no expire_time", order.client_order_id));
} Try / catch
match provider.submit_order(order) {
Err(e) if e.to_string().contains("GTD time in force requires expire_time") => {
// resubmit as GTC or attach expire_time
}
other => other,
} Prevention
- Make expire_time a required field of your GTD order constructor.
- Default GTD orders to an explicit expiry computed at strategy level.
- Add an order-validation unit test covering every TimeInForce variant.
- Use Gtc when no meaningful expiry exists.
When it happens
Trigger: Calling build_add_order_params or build_batch_order with an order whose time_in_force is Gtd while the expire_time option is None.
Common situations: Building orders from a strategy that sets TIF=Gtd but never sets expiry; mapping an upstream order request that carries Gtd without an expiry field; tests like test_compute_ws_time_in_force_fok_bails exercising TIF handling.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- FOK time in force is not supported on Kraken WS v2; use REST
- Unsupported time in force: {time_in_force:?}
- limit_price is required for batch order type {order_type:?}
- Conditional orders require a trigger price
- post-only Derive orders only support GTC time in force; rece
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3ea90ccd0c5a86ce.
Report an issue: GitHub.