{"record":{"id":"f561cfad3c4f8819","repo":"nautechsystems/nautilus_trader","slug":"signature-expiry-overflows-derive-signature-expiry","errorCode":null,"errorMessage":"signature expiry overflows Derive signature_expiry_sec: now {now_secs}s plus TTL {ttl_secs}s","messagePattern":"signature expiry overflows Derive signature_expiry_sec: now (.+?)s plus TTL (.+?)s","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/derive/src/execution.rs","lineNumber":3068,"sourceCode":"    let min_ttl_secs = MIN_SIGNATURE_TTL.as_secs();\n    if signature_expiry_secs <= min_ttl_secs {\n        anyhow::bail!(\n            \"signature_expiry_secs {signature_expiry_secs}s must be greater than the Derive minimum {min_ttl_secs}s\"\n        );\n    }\n\n    let now_secs_u64 = clock.get_time_ns().as_u64() / 1_000_000_000;\n    let now_secs = i64::try_from(now_secs_u64).with_context(|| {\n        format!(\"current UNIX time {now_secs_u64}s cannot fit in Derive signature_expiry_sec\")\n    })?;\n    let ttl_secs = i64::try_from(signature_expiry_secs).with_context(|| {\n        format!(\n            \"signature_expiry_secs {signature_expiry_secs}s cannot fit in Derive signature_expiry_sec\"\n        )\n    })?;\n\n    now_secs.checked_add(ttl_secs).ok_or_else(|| {\n        anyhow::anyhow!(\n            \"signature expiry overflows Derive signature_expiry_sec: now {now_secs}s plus TTL {ttl_secs}s\"\n        )\n    })\n}\n\nasync fn refresh_market_order_quote(\n    http_client: &DeriveHttpClient,\n    venue_symbol: &str,\n    instrument: &DeriveInstrument,\n    clock: &'static AtomicTime,\n) -> anyhow::Result<QuoteTick> {\n    let ticker = http_client.get_ticker(venue_symbol).await?;\n    let price_precision = Price::from_decimal(instrument.tick_size)\n        .with_context(|| format!(\"invalid Derive tick_size for {venue_symbol}\"))?\n        .precision;\n    let size_precision = Quantity::from_decimal(instrument.amount_step)\n        .with_context(|| format!(\"invalid Derive amount_step for {venue_symbol}\"))?\n        .precision;","sourceCodeStart":3050,"sourceCodeEnd":3086,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/derive/src/execution.rs#L3050-L3086","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set the signature TTL to a sane number of seconds (e.g. tens of seconds to a few minutes).","Verify the config field is in seconds, not milliseconds or another unit.","Check system clock sanity (NTP) if now_secs looks wrong in the message.","Reproduce with the printed now/TTL values to confirm which operand is out of range."],"exampleFix":"// before\nlet ttl_secs = u64::MAX; // intended \"never expires\"\n// after\nlet ttl_secs = 30; // 30-second signature window","handlingStrategy":"validation","validationCode":"fn validate_signature_ttl(ttl_secs: u64) -> Result<(), String> {\n    const MAX_SANE_TTL: u64 = 3600;\n    if ttl_secs > MAX_SANE_TTL {\n        return Err(format!(\"signature TTL {ttl_secs}s is unreasonably large\"));\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match compute_signature_expiry(now_secs, ttl_secs) {\n    Ok(expiry) => /* sign request */,\n    Err(e) if e.to_string().contains(\"overflows\") => {\n        log::error!(\"bad TTL config: {e}\");\n        // fall back to a default TTL before retrying\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep signature TTLs to sane values (seconds to minutes)","Confirm the TTL config unit is seconds","Sync the system clock with NTP so now_secs is trustworthy"],"tags":["derive","auth","signature","overflow","config"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}