nautechsystems/nautilus_trader · error

Missing server timestamp (us_out) in response

Error message

Missing server timestamp (us_out) in response

What it means

Deribit's account-state and instrument responses include the server clock field us_out, which Nautilus uses as the event/report timestamp (converted from microseconds to UnixNanos). extract_server_timestamp raises this error when us_out is absent (None) from the parsed JSON response, since a valid timestamp is mandatory for the resulting events.

Source

Thrown at crates/adapters/deribit/src/common/parse.rs:154

        return false;
    };

    if seg.is_empty() || seg == "PERPETUAL" {
        return false;
    }
    // Combo strategy codes are alphabetic; date segments start with a digit.
    seg.chars().next().is_some_and(|c| c.is_ascii_alphabetic())
        && seg.chars().all(|c| c.is_ascii_alphabetic())
}

/// Extracts server timestamp from response and converts to UnixNanos.
///
/// # Errors
///
/// Returns an error if the server timestamp (us_out) is missing from the response.
pub fn extract_server_timestamp(us_out: Option<u64>) -> anyhow::Result<UnixNanos> {
    let us_out =
        us_out.ok_or_else(|| anyhow::anyhow!("Missing server timestamp (us_out) in response"))?;
    Ok(UnixNanos::from(us_out * NANOSECONDS_IN_MICROSECOND))
}

/// Parses a Deribit instrument into a Nautilus [`InstrumentAny`].
///
/// Returns `Ok(None)` for unsupported instrument types.
///
/// # Errors
///
/// Returns an error if:
/// - Required fields are missing (e.g., strike price for options)
/// - Timestamp conversion fails
/// - Decimal conversion fails for fees
pub fn parse_deribit_instrument_any(
    instrument: &DeribitInstrument,
    ts_init: UnixNanos,
    ts_event: UnixNanos,
) -> anyhow::Result<Option<InstrumentAny>> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log/inspect the raw JSON response to confirm whether us_out is present and the response is actually a success result, not a JSON-RPC error.
  2. Handle JSON-RPC error envelopes before calling the parser so error payloads don't reach extract_server_timestamp.
  3. Upgrade the nautilus deribit adapter in case the Deribit API changed the response shape.
  4. Fix test fixtures/mocks to include `us_out` in account.state and instrument responses.

Example fix

// before
let parsed = json.as_object().ok_or(...)?;
let ts = extract_server_timestamp(parsed["result"]["us_out"].as_u64())?;

// after
if let Some(err) = json["error"].as_object() {
    return Err(anyhow!("Deribit JSON-RPC error: {err:?}"));
}
let ts = extract_server_timestamp(json["result"]["us_out"].as_u64())?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust
let us_out = response
    .get("result")
    .and_then(|r| r.get("us_out"))
    .and_then(|v| v.as_u64());
if us_out.is_none() {
    // likely a JSON-RPC error envelope; surface it instead
    anyhow::bail!("Deribit response missing us_out: {response}");
}

Type guard

fn has_server_timestamp(resp: &serde_json::Value) -> bool {
    resp["result"]["us_out"].is_u64()
}

Try / catch

match extract_server_timestamp(us_out) {
    Ok(ts) => ts,
    Err(e) if e.to_string().contains("us_out") => {
        log::error!("Deribit response missing us_out — check raw payload/API version");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling request_account_state, request_instruments/request_instrument, or parsing an account.state response whose JSON lacks the `us_out` field — e.g. an error payload parsed as a success payload, an API change in the response envelope, or a mocked/partial JSON fixture without us_out.

Common situations: Deribit API version change removing/renaming us_out in some endpoints; handling error responses (JSON-RPC error) through the success parser; custom test fixtures missing the field.

Related errors


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