nautechsystems/nautilus_trader · error · anyhow::Error
Invalid trade_id format
Error message
Invalid trade_id format
What it means
Kraken Spot trade responses put the trade id at array index 6, expected either as an integer or a string. If the JSON value there is neither (e.g. null, object, number that is not an i64), parse_trade_tick_from_array bails with 'Invalid trade_id format' because a TradeId cannot be constructed.
Source
Thrown at crates/adapters/kraken/src/common/parse.rs:543
let ts_event = parse_millis_timestamp(time, "trade.time")?;
let side_str = trade_array
.get(3)
.and_then(|v| v.as_str())
.context("Missing or invalid side")?;
let aggressor = match side_str {
"b" => AggressorSide::Buy,
"s" => AggressorSide::Sell,
_ => AggressorSide::NoAggressor,
};
let trade_id_value = trade_array.get(6).context("Missing trade_id")?;
let trade_id = if let Some(id) = trade_id_value.as_i64() {
TradeId::new_checked(id.to_string())?
} else if let Some(id_str) = trade_id_value.as_str() {
TradeId::new_checked(id_str)?
} else {
anyhow::bail!("Invalid trade_id format");
};
TradeTick::new_checked(
instrument.id(),
price,
size,
aggressor,
trade_id,
ts_event,
ts_init,
)
.context("Failed to construct TradeTick from Kraken trade")
}
/// Parses a Kraken Futures public execution into a Nautilus trade tick.
///
/// # Errors
///View on GitHub (pinned to 18893faf8b)
Solutions
- Log the raw trade array and check element 6's actual JSON type to see what Kraken returned.
- Update the adapter to the latest version in case Kraken changed the Trades schema.
- If Kraken legitimately emits a new format, convert it to a string before TradeId::new_checked (or patch parse to handle the type).
Example fix
// before
} else {
anyhow::bail!("Invalid trade_id format");
};
// after (if Kraken sends floats)
} else if let Some(f) = trade_id_value.as_f64() {
TradeId::new_checked(format!("{f:.0}"))?
} else {
anyhow::bail!("Invalid trade_id format");
}; Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the raw Kraken trade array before parsing
fn has_valid_trade_id(arr: &serde_json::Value) -> bool {
arr.get(6).map(|v| v.is_i64() || v.is_string()).unwrap_or(false)
} Type guard
fn trade_id_is_parseable(v: &serde_json::Value) -> bool {
v.is_i64() || v.is_string()
} Try / catch
match parse_trade_tick_from_array(&arr, instrument, ts_init) {
Ok(tick) => emit(tick),
Err(e) if e.to_string().contains("trade_id") => {
log::warn!("skipping malformed trade: {arr:?}");
}
Err(e) => return Err(e),
} Prevention
- Log raw payloads when the Kraken adapter version changes.
- Keep the adapter updated after Kraken API schema changes.
- Add fixture tests using live Kraken Trades responses.
When it happens
Trigger: request_trades calls parse_trade_tick_from_array on a Kraken /Trades response where element 6 of a trade array is neither an i64-representable number nor a string (unexpected API payload shape).
Common situations: Kraken changing or extending the Trades payload; some trades returning non-standard identifiers; test fixtures with malformed arrays; hitting a different endpoint version.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- Kraken Spot does not support the demo environment
- expected 2 impact prices, received {len}
- Trailing stop orders are not yet supported on the Kraken WS
- Iceberg (display_qty) orders are not supported on the Kraken
- Unsupported order type for Kraken WS: {order_type:?}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/2310af0179c4c4dc.
Report an issue: GitHub.