{"record":{"id":"97aeb6ac72ccac9a","repo":"nautechsystems/nautilus_trader","slug":"polymarket-public-trades-api-reached-the-historica","errorCode":null,"errorMessage":"Polymarket public trades API reached the historical offset ceiling for condition {}; cannot guarantee complete start-anchored results, narrow the time window","messagePattern":"Polymarket public trades API reached the historical offset ceiling for condition (.+?); cannot guarantee complete start-anchored results, narrow the time window","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/http/data_api.rs","lineNumber":178,"sourceCode":"    type Stop = TradeTickStop;\n\n    fn consume(&mut self, rows: Vec<DataApiTrade>) -> anyhow::Result<Option<Self::Stop>> {\n        self.rows.extend(rows);\n        let capped = self.start.is_none()\n            && self.limit.is_some_and(|target| {\n                count_matching_trades_within_end(&self.rows, &self.token_id, self.end) >= target\n            });\n        Ok(capped.then_some(TradeTickStop::CallerCapped))\n    }\n\n    fn finish(self, completion: &Completion<Self::Stop>) -> anyhow::Result<Self::Output> {\n        if self.start.is_some()\n            && matches!(\n                completion,\n                Completion::Stopped(TradeTickStop::VenueOffsetCeiling(_))\n            )\n        {\n            anyhow::bail!(\n                \"Polymarket public trades API reached the historical offset ceiling for condition {}; cannot guarantee complete start-anchored results, narrow the time window\",\n                self.condition_id\n            );\n        }\n\n        let start_secs = self\n            .start\n            .map(|value| (value.as_u64() / 1_000_000_000) as i64);\n        let end_secs = self\n            .end\n            .map(|value| (value.as_u64() / 1_000_000_000) as i64);\n        let mut trades = parse_trade_ticks(\n            self.rows,\n            self.instrument_id,\n            &self.token_id,\n            self.price_precision,\n            self.size_precision,\n        )?;","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/http/data_api.rs#L160-L196","documentation":"The Polymarket public trades endpoint caps pagination at an offset ceiling (10,000). When a start-anchored backfill (start is set) stops because it hit TradeTickStop::VenueOffsetCeiling, the adapter cannot guarantee the fetched data covers all trades back to the requested start, so it fails instead of returning silently incomplete history.","triggerScenarios":"request_trade_ticks with a start timestamp far enough in the past that more than MAX_OFFSET (10,000) worth of paginated trades exists for the condition; the pagination loop finishes with Completion::Stopped(TradeTickStop::VenueOffsetCeiling).","commonSituations":"Requesting full trade history for a very liquid market since inception; long historical backfills after long downtime; start anchored at epoch or market launch date on high-volume conditions.","solutions":["Narrow the requested time window (raise start) so fewer than 10,000 trades fall within the range.","Backfill history in multiple smaller windows, paginating between them, and stitch the results.","If you do not need start-anchored completeness, omit start (end-anchored fetches are allowed to stop at the ceiling).","Use an alternative data source (e.g. the Data API endpoint) for full deep history of high-volume markets."],"exampleFix":"// before: one huge window hits the venue offset ceiling\nlet ticks = api.request_trade_ticks(Some(condition_id), Some(launch_ts), Some(now), None).await?;\n// after: chunk the range into windows below the ceiling\nfor (s, e) in chunk_range(launch_ts, now, max_window) {\n    let ticks = api.request_trade_ticks(Some(condition_id), Some(s), Some(e), None).await?;\n    sink.extend(ticks);\n}","handlingStrategy":"fallback","validationCode":"// Rust: estimate trade count before requesting deep history\nlet approx_trades = market.avg_trades_per_day * days_since(start);\nlet needs_windowing = approx_trades > 10_000;","typeGuard":null,"tryCatchPattern":"// Rust\nmatch api.request_trade_ticks(Some(cid), Some(start), Some(end), None).await {\n    Ok(ticks) => Ok(ticks),\n    Err(e) if e.to_string().contains(\"offset ceiling\") => windowed_backfill(&api, &cid, start, end).await,\n    Err(e) => Err(e),\n}","preventionTips":["Chunk long historical ranges into windows well below 10,000 trades.","For very liquid markets, prefer end-anchored fetches or an alternative history source.","Document the venue pagination ceiling in your backfill planning."],"tags":["polymarket","data-api","pagination","historical-data","rust"],"backgroundTag":"value-out-of-range","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"}