{"record":{"id":"1db679c7a2529688","repo":"nautechsystems/nautilus_trader","slug":"polymarket-data-api-returned-trade-for-condition","errorCode":null,"errorMessage":"Polymarket Data API returned trade for condition {} while requesting {expected_condition_id}","messagePattern":"Polymarket Data API returned trade for condition (.+?) while requesting (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/http/data_api.rs","lineNumber":120,"sourceCode":"            encode_decimal(&mut descriptor, trade.price);\n            encode_decimal(&mut descriptor, trade.size);\n            descriptor.extend_from_slice(&trade.timestamp.to_be_bytes());\n            descriptor\n        })\n        .collect();\n    fingerprint_multiset(2, descriptors)\n}\n\nfn validate_trade_page_scope(\n    rows: Vec<DataApiTrade>,\n    expected_condition_id: &str,\n) -> anyhow::Result<Vec<DataApiTrade>> {\n    match rows.iter().find(|trade| {\n        !trade\n            .condition_id\n            .eq_ignore_ascii_case(expected_condition_id)\n    }) {\n        Some(trade) => anyhow::bail!(\n            \"Polymarket Data API returned trade for condition {} while requesting {expected_condition_id}\",\n            trade.condition_id\n        ),\n        None => Ok(rows),\n    }\n}\n\nfn encode_decimal(output: &mut Vec<u8>, value: Decimal) {\n    let normalized = value.normalize();\n    output.extend_from_slice(&normalized.mantissa().to_be_bytes());\n    output.extend_from_slice(&normalized.scale().to_be_bytes());\n}\n\n#[derive(Clone, Debug, Eq, PartialEq)]\nenum TradeTickStop {\n    CallerCapped,\n    VenueOffsetCeiling(OffsetCeilingSource),\n}","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/http/data_api.rs#L102-L138","documentation":"validate_trade_page_scope checks that every trade row returned by a Data API page matches the condition_id that was requested. If any row's condition_id differs (case-insensitively), the API violated the request scope and the adapter bails instead of emitting ticks for the wrong market.","triggerScenarios":"Fetching trade ticks via FetchOutcome::Page when the Polymarket Data API returns a page containing a trade whose condition_id does not equal the expected_condition_id of the request.","commonSituations":"Upstream API behavior changes or bugs returning cross-market rows; condition ids differing only in case are tolerated, so this fires only on genuinely different conditions; stale or manipulated cached API responses; proxy/mirror endpoints serving aggregated data.","solutions":["Retry the fetch — a transient upstream bug may return the correct scope on a subsequent request.","Verify the expected_condition_id used in the request is correct (copy it from the market's gamma metadata).","Check for a misconfigured Data API base URL or proxy returning data for the wrong market.","Report/inspect the offending trade's condition_id (it is included in the message) to identify the scope violation source."],"exampleFix":"// before: trusting API pages blindly\nlet trades = data_api.fetch_trades_page(&condition_id, offset).await?;\n// after: the library already validates; handle the failure explicitly\nmatch data_api.fetch_trades_page(&condition_id, offset).await {\n    Ok(trades) => process(trades),\n    Err(e) if e.to_string().contains(\"while requesting\") => retry_with_backoff(&condition_id, offset),\n    Err(e) => return Err(e),\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rust\nmatch fetch_page(&condition_id, offset).await {\n    Ok(rows) => Ok(rows),\n    Err(e) if e.to_string().contains(\"while requesting\") => {\n        warn!(\"scope violation from Data API, retrying\");\n        retry_with_backoff(|| fetch_page(&condition_id, offset)).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Pin trusted Data API endpoints and verify condition ids from gamma market metadata.","Alert on scope-violation errors — repeated occurrences indicate upstream regression, not client bug.","Avoid third-party mirror endpoints that may aggregate across conditions."],"tags":["polymarket","data-api","scope-violation","rust"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}