nautechsystems/nautilus_trader · error
Failed to parse clob_token_ids '{}': {e}
Error message
Failed to parse clob_token_ids '{}': {e} What it means
parse_gamma_market expects the market's clob_token_ids field to be a JSON string containing a JSON array (Polymarket returns it as a stringified array). serde_json::from_str fails when the string is not valid JSON or is not an array of strings, producing this error.
Source
Thrown at crates/adapters/polymarket/src/http/parse.rs:111
/// numeric and composite `<uuid>:<away>:<home>` forms.
pub game_id: Option<String>,
}
/// Parses a Gamma market response into instrument definitions.
///
/// Each market produces two definitions: one for the Yes outcome
/// and one for the No outcome.
pub fn parse_gamma_market(market: &GammaMarket) -> anyhow::Result<Vec<PolymarketInstrumentDef>> {
let game_id = market.game_id.clone().or_else(|| {
market
.events
.as_ref()?
.iter()
.find_map(|event| event.game_id.clone())
});
let token_ids: Vec<String> = serde_json::from_str(&market.clob_token_ids).map_err(|e| {
anyhow::anyhow!(
"Failed to parse clob_token_ids '{}': {e}",
market.clob_token_ids
)
})?;
if token_ids.len() != 2 {
anyhow::bail!("Expected 2 token IDs, received {}", token_ids.len());
}
let outcomes: Vec<String> = serde_json::from_str(&market.outcomes)
.map_err(|e| anyhow::anyhow!("Failed to parse outcomes '{}': {e}", market.outcomes))?;
if outcomes.len() != 2 {
anyhow::bail!("Expected 2 outcomes, received {}", outcomes.len());
}
let tick_size = market
.order_price_min_tick_sizeView on GitHub (pinned to 18893faf8b)
Solutions
- Log the raw market.clob_token_ids value to see the actual payload shape.
- If the field arrives as a real array (not a string), parse it with serde_json::from_value or update the GammaMarket struct to use an untagged/ custom deserializer.
- Report/handle the Gamma schema change and pin to a known-good API behavior; skip markets with unparseable token ids.
Example fix
// before
let token_ids: Vec<String> = serde_json::from_str(&market.clob_token_ids)...;
// after
let token_ids: Vec<String> = match serde_json::from_str(&market.clob_token_ids) {
Ok(v) => v,
Err(_) => serde_json::from_value(market.clob_token_ids_raw.clone())?, // handles non-string shapes
}; Defensive patterns
Strategy: validation
Validate before calling
fn has_stringified_token_ids(market: &GammaMarket) -> bool {
!market.clob_token_ids.is_empty()
&& market.clob_token_ids.starts_with('[')
&& serde_json::from_str::<Vec<String>>(&market.clob_token_ids).is_ok()
} Type guard
fn parse_token_ids(raw: &str) -> Option<Vec<String>> {
serde_json::from_str::<Vec<String>>(raw).ok()
} Try / catch
let token_ids = match serde_json::from_str::<Vec<String>>(&market.clob_token_ids) {
Ok(v) => v,
Err(e) => { warn!("skipping market {}: bad clob_token_ids: {e}", market.id); return Ok(None); }
}; Prevention
- Pin and monitor the Gamma API response schema; alert on field-shape changes.
- Never hand-construct GammaMarket fixtures with non-stringified arrays.
- Parse markets defensively: skip unparseable markets instead of failing the whole batch.
When it happens
Trigger: Gamma API returning clob_token_ids as an actual JSON array instead of a string, an empty string, or malformed/quoted-inconsistently content while parsing a market into instruments.
Common situations: Gamma API schema changes, proxy/mock servers re-serializing the field differently, or truncated/empty responses from the events endpoint.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse outcomes '{}': {e}
- Expected 2 token IDs, received {}
- Expected 2 outcomes, received {}
- invalid signed E18 integer for {field}: {value}
- Empty book snapshot for {instrument_id}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e7914876e3da75ea.
Report an issue: GitHub.