{"record":{"id":"e7914876e3da75ea","repo":"nautechsystems/nautilus_trader","slug":"failed-to-parse-clob-token-ids-e","errorCode":null,"errorMessage":"Failed to parse clob_token_ids '{}': {e}","messagePattern":"Failed to parse clob_token_ids '(.+?)': (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/http/parse.rs","lineNumber":111,"sourceCode":"    /// numeric and composite `<uuid>:<away>:<home>` forms.\n    pub game_id: Option<String>,\n}\n\n/// Parses a Gamma market response into instrument definitions.\n///\n/// Each market produces two definitions: one for the Yes outcome\n/// and one for the No outcome.\npub fn parse_gamma_market(market: &GammaMarket) -> anyhow::Result<Vec<PolymarketInstrumentDef>> {\n    let game_id = market.game_id.clone().or_else(|| {\n        market\n            .events\n            .as_ref()?\n            .iter()\n            .find_map(|event| event.game_id.clone())\n    });\n\n    let token_ids: Vec<String> = serde_json::from_str(&market.clob_token_ids).map_err(|e| {\n        anyhow::anyhow!(\n            \"Failed to parse clob_token_ids '{}': {e}\",\n            market.clob_token_ids\n        )\n    })?;\n\n    if token_ids.len() != 2 {\n        anyhow::bail!(\"Expected 2 token IDs, received {}\", token_ids.len());\n    }\n\n    let outcomes: Vec<String> = serde_json::from_str(&market.outcomes)\n        .map_err(|e| anyhow::anyhow!(\"Failed to parse outcomes '{}': {e}\", market.outcomes))?;\n\n    if outcomes.len() != 2 {\n        anyhow::bail!(\"Expected 2 outcomes, received {}\", outcomes.len());\n    }\n\n    let tick_size = market\n        .order_price_min_tick_size","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/http/parse.rs#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"Gamma API schema changes, proxy/mock servers re-serializing the field differently, or truncated/empty responses from the events endpoint.","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."],"exampleFix":"// before\nlet token_ids: Vec<String> = serde_json::from_str(&market.clob_token_ids)...;\n// after\nlet token_ids: Vec<String> = match serde_json::from_str(&market.clob_token_ids) {\n    Ok(v) => v,\n    Err(_) => serde_json::from_value(market.clob_token_ids_raw.clone())?, // handles non-string shapes\n};","handlingStrategy":"validation","validationCode":"fn has_stringified_token_ids(market: &GammaMarket) -> bool {\n    !market.clob_token_ids.is_empty()\n        && market.clob_token_ids.starts_with('[')\n        && serde_json::from_str::<Vec<String>>(&market.clob_token_ids).is_ok()\n}","typeGuard":"fn parse_token_ids(raw: &str) -> Option<Vec<String>> {\n    serde_json::from_str::<Vec<String>>(raw).ok()\n}","tryCatchPattern":"let token_ids = match serde_json::from_str::<Vec<String>>(&market.clob_token_ids) {\n    Ok(v) => v,\n    Err(e) => { warn!(\"skipping market {}: bad clob_token_ids: {e}\", market.id); return Ok(None); }\n};","preventionTips":["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."],"tags":["rust","json","parsing","polymarket"],"backgroundTag":"json-unmarshal-failed","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"}