nautechsystems/nautilus_trader · error
RTDS TWAP topic {:?} requires window_s={}, received {}
Error message
RTDS TWAP topic {:?} requires window_s={}, received {} What it means
Raised when a crypto TWAP message arrives whose payload window_s does not match the window implied by its topic (30 for crypto_prices_twap_thirty, 60 for crypto_prices_twap_sixty). The topic and payload disagree, so trusting the payload would corrupt the price series; the feed validates and bails. This guards against upstream protocol changes or misrouted messages.
Source
Thrown at crates/adapters/polymarket/src/rtds.rs:1305
self.emit_custom_payload(&custom_payload, data_types.clone());
}
}
fn handle_crypto_twap_update(
&self,
envelope: &RtdsEnvelope,
window: RtdsCryptoTwapWindow,
) -> anyhow::Result<()> {
let topic = window.topic();
if !self.has_topic_subscription(topic.as_str()) {
return Ok(());
}
let payload: CryptoTwapPayloadRaw = serde_json::from_str(envelope.payload.get())
.map_err(|e| anyhow::anyhow!("invalid RTDS crypto TWAP payload: {e}"))?;
if payload.window_s != window.seconds() {
anyhow::bail!(
"RTDS TWAP topic {:?} requires window_s={}, received {}",
topic.as_str(),
window.seconds(),
payload.window_s,
);
}
let symbol_lower = payload.symbol.to_ascii_lowercase();
let value =
decimal_from_signed_e18("full_accuracy_value", payload.full_accuracy_value.as_str())?;
let ts_event = unix_nanos_from_millis("payload.timestamp", payload.timestamp)?;
unix_nanos_from_millis("envelope.timestamp", envelope.timestamp)?;
let Some(data_types) =
self.admit_twap_observation(topic, &symbol_lower, payload.timestamp, value)?
else {
return Ok(());
};
let ts_init = self.inner.clock.get_time_ns();View on GitHub (pinned to 18893faf8b)
Solutions
- Upgrade the adapter in case upstream changed topic/window semantics and a fix exists.
- Capture the full envelope (topic + payload) and report the mismatch to the venue/adapter maintainers.
- If replaying recorded data, regenerate fixtures so payload.window_s matches the topic's required window.
- As a stopgap, drop the subscription to the offending topic if the data is not required.
Example fix
// before
// fixture: topic "crypto_prices_twap_thirty" with window_s=60
{"topic":"crypto_prices_twap_thirty","payload":"{\"window_s\":60,...}"}
// after
{"topic":"crypto_prices_twap_thirty","payload":"{\"window_s\":30,...}"} Defensive patterns
Strategy: validation
Validate before calling
fn twap_window_matches(topic: &str, window_s: u64) -> bool {
matches!((topic, window_s), ("crypto_prices_twap_thirty", 30) | ("crypto_prices_twap_sixty", 60))
} Type guard
fn parse_twap_payload(topic: &str, raw: &str) -> anyhow::Result<CryptoTwapPayloadRaw> {
let p: CryptoTwapPayloadRaw = serde_json::from_str(raw)?;
let required = if topic.ends_with("thirty") { 30 } else { 60 };
anyhow::ensure!(p.window_s == required, "window_s {} != required {required}", p.window_s);
Ok(p)
} Try / catch
match feed.next_event().await {
Err(e) if e.to_string().contains("RTDS TWAP topic") => {
log::error!("TWAP topic/payload mismatch (upstream protocol change?): {e}");
}
other => { /* normal handling */ }
} Prevention
- Validate recorded/replayed fixtures so window_s matches each topic's window.
- Track upstream RTDS schema changes for TWAP payloads.
- Keep the adapter updated so window semantics stay in sync with the venue.
- Treat this error as a data-integrity alarm, not a transient failure — do not auto-retry.
When it happens
Trigger: RTDS delivers a TWAP message on crypto_prices_twap_thirty with payload.window_s != 30 (or the sixty variant with window_s != 60) — e.g. Polymarket changes window units or routes messages to the wrong topic.
Common situations: Upstream API changing TWAP payload semantics; misrouted messages from the publisher; replaying recorded fixtures with mismatched topic/payload pairs.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- order price must be in (0, 1)
- invalid order quantity
- trade quantity must be positive
- trade price must be in (0, 1)
- Not a subscription channel: {kind}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4f049d098423bc60.
Report an issue: GitHub.