nautechsystems/nautilus_trader · error

signature expiry overflows Derive signature_expiry_sec: now

Error message

signature expiry overflows Derive signature_expiry_sec: now {now_secs}s plus TTL {ttl_secs}s

What it means

When building Derive authentication signatures, the adapter computes expiry as now + TTL using checked_add on u64 seconds. If the addition overflows (astronomically large TTL or clock value), it refuses and raises this message showing both operands. This guards against silently wrapping the expiry timestamp, which would produce an invalid or already-expired signature.

Source

Thrown at crates/adapters/derive/src/execution.rs:3068

    let min_ttl_secs = MIN_SIGNATURE_TTL.as_secs();
    if signature_expiry_secs <= min_ttl_secs {
        anyhow::bail!(
            "signature_expiry_secs {signature_expiry_secs}s must be greater than the Derive minimum {min_ttl_secs}s"
        );
    }

    let now_secs_u64 = clock.get_time_ns().as_u64() / 1_000_000_000;
    let now_secs = i64::try_from(now_secs_u64).with_context(|| {
        format!("current UNIX time {now_secs_u64}s cannot fit in Derive signature_expiry_sec")
    })?;
    let ttl_secs = i64::try_from(signature_expiry_secs).with_context(|| {
        format!(
            "signature_expiry_secs {signature_expiry_secs}s cannot fit in Derive signature_expiry_sec"
        )
    })?;

    now_secs.checked_add(ttl_secs).ok_or_else(|| {
        anyhow::anyhow!(
            "signature expiry overflows Derive signature_expiry_sec: now {now_secs}s plus TTL {ttl_secs}s"
        )
    })
}

async fn refresh_market_order_quote(
    http_client: &DeriveHttpClient,
    venue_symbol: &str,
    instrument: &DeriveInstrument,
    clock: &'static AtomicTime,
) -> anyhow::Result<QuoteTick> {
    let ticker = http_client.get_ticker(venue_symbol).await?;
    let price_precision = Price::from_decimal(instrument.tick_size)
        .with_context(|| format!("invalid Derive tick_size for {venue_symbol}"))?
        .precision;
    let size_precision = Quantity::from_decimal(instrument.amount_step)
        .with_context(|| format!("invalid Derive amount_step for {venue_symbol}"))?
        .precision;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the signature TTL to a sane number of seconds (e.g. tens of seconds to a few minutes).
  2. Verify the config field is in seconds, not milliseconds or another unit.
  3. Check system clock sanity (NTP) if now_secs looks wrong in the message.
  4. Reproduce with the printed now/TTL values to confirm which operand is out of range.

Example fix

// before
let ttl_secs = u64::MAX; // intended "never expires"
// after
let ttl_secs = 30; // 30-second signature window
Defensive patterns

Strategy: validation

Validate before calling

fn validate_signature_ttl(ttl_secs: u64) -> Result<(), String> {
    const MAX_SANE_TTL: u64 = 3600;
    if ttl_secs > MAX_SANE_TTL {
        return Err(format!("signature TTL {ttl_secs}s is unreasonably large"));
    }
    Ok(())
}

Try / catch

match compute_signature_expiry(now_secs, ttl_secs) {
    Ok(expiry) => /* sign request */,
    Err(e) if e.to_string().contains("overflows") => {
        log::error!("bad TTL config: {e}");
        // fall back to a default TTL before retrying
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Configuring a signature TTL so large that now_secs + ttl_secs exceeds u64::MAX seconds; passing a nonsensical/garbage TTL value (e.g. from a mis-parsed config) into the signing routine.

Common situations: TTL set to u64::MAX or some sentinel 'forever' value in config; unit misconfiguration (e.g. providing milliseconds instead of seconds); clock corruption producing absurd now_secs.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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