nautechsystems/nautilus_trader · error

Unsupported time in force: {time_in_force:?}

Error message

Unsupported time in force: {time_in_force:?}

What it means

The Kraken Spot order-request builder supports only a limited set of time-in-force values (with GTD additionally requiring an expire_time). Any other TimeInForce variant reaching this match arm is rejected, since there is no Kraken Spot mapping for it.

Source

Thrown at crates/adapters/kraken/src/http/spot/client.rs:3257

    time_in_force: TimeInForce,
    expire_time: Option<UnixNanos>,
) -> anyhow::Result<(Option<String>, Option<String>)> {
    if !is_limit_order {
        return Ok((None, None));
    }

    match time_in_force {
        TimeInForce::Gtc => Ok((None, None)),
        TimeInForce::Ioc => Ok((Some("IOC".to_string()), None)),
        TimeInForce::Fok => Ok((Some("FOK".to_string()), None)),
        TimeInForce::Gtd => {
            let expire = expire_time.ok_or_else(|| {
                anyhow::anyhow!("GTD time in force requires expire_time parameter")
            })?;
            let expire_secs = expire.as_u64() / NANOSECONDS_IN_SECOND;
            Ok((Some("GTD".to_string()), Some(expire_secs.to_string())))
        }
        _ => anyhow::bail!("Unsupported time in force: {time_in_force:?}"),
    }
}

#[cfg(test)]
mod tests {
    use std::{sync::Arc, time::Duration};

    use nautilus_model::instruments::CurrencyPair;
    use rstest::rstest;

    use super::*;

    #[rstest]
    fn test_raw_client_creation() {
        let client = KrakenSpotRawHttpClient::default();
        assert!(client.credential.is_none());
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use a supported time in force (GTC, IOC, FOK, or GTD with expire_time set) for Kraken Spot orders.
  2. When using GTD, also pass expire_time — it is required and converted to seconds.
  3. Omit time_in_force to use the venue default.
  4. If the variant should be supported, check adapter version/CHANGELOG for added Kraken TIF mappings or file an upstream feature request.

Example fix

// before
time_in_force: TimeInForce::AtTheOpen
// after
time_in_force: TimeInForce::Gtc
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_TIF: &[TimeInForce] = &[TimeInForce::Gtc, TimeInForce::Ioc, TimeInForce::Fok, TimeInForce::Gtd];
if let Some(tif) = time_in_force {
    if !SUPPORTED_TIF.contains(tif) {
        return Err(format!("Kraken Spot unsupported TIF: {tif:?}"));
    }
    if *tif == TimeInForce::Gtd && expire_time.is_none() {
        return Err("GTD requires expire_time");
    }
}

Try / catch

match submit_result {
    Err(e) if e.to_string().contains("Unsupported time in force") => {
        // retry with TimeInForce::Gtc or venue default
    }
    r => r?,
}

Prevention

When it happens

Trigger: Submitting a Kraken Spot order with time_in_force set to an unsupported variant (falling into the catch-all _ arm) — e.g. TimeInForce::AtTheOpen, Day variants without a mapping, or other exchange-specific TIF values.

Common situations: Strategy defaults carrying a TIF configured for another venue; recently added TimeInForce enum variants not yet mapped in the Kraken adapter; typo-level mismatches between enum variants across versions.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/e3a7e3f77b4edc69. Report an issue: GitHub.