nautechsystems/nautilus_trader · error
Failed to parse fill report for {}: {e}
Error message
Failed to parse fill report for {}: {e} What it means
While generating fill (execution) reports from listCurrentOrders/cleared orders, the placed_date timestamp on each Betfair order must be parsed by parse_betfair_timestamp. An unparseable timestamp aborts the fill report for that bet_id with this wrapped error.
Source
Thrown at crates/adapters/betfair/src/execution.rs:4249
orders: &[CurrentOrderSummary],
fill_tracker: &mut FillTracker,
customer_order_refs: &AHashMap<String, CustomerOrderRefResolution>,
account_id: AccountId,
currency: Currency,
ts_init: UnixNanos,
) -> anyhow::Result<Vec<FillReport>> {
let mut reports = Vec::new();
for order in orders {
let size_matched = order.size_matched.unwrap_or(Decimal::ZERO);
let size_voided = order.size_voided.unwrap_or(Decimal::ZERO);
let gross_matched = size_matched + size_voided;
if gross_matched == Decimal::ZERO {
continue;
}
parse_betfair_timestamp(&order.placed_date).map_err(|e| {
anyhow::anyhow!("Failed to parse fill report for {}: {e}", order.bet_id)
})?;
let has_applied_fill_lots = fill_tracker.has_fill_lots(&order.bet_id);
let cumulative = if has_applied_fill_lots {
gross_matched
} else {
size_matched
};
let incremental_fill = if has_applied_fill_lots && size_voided > Decimal::ZERO {
fill_tracker.advance_cumulative_fill_with_voids(
&order.bet_id,
cumulative,
size_voided,
order.average_price_matched,
order.price_size.price,
)
} else {
fill_tracker.advance_cumulative_fill(View on GitHub (pinned to 18893faf8b)
Solutions
- Log the raw placed_date value for the reported bet_id and compare against the expected format.
- Extend parse_betfair_timestamp to accept the observed format (e.g. fractional seconds present or absent).
- Skip or default the timestamp for records where placed_date is legitimately absent, if business-appropriate.
Example fix
// before
parse_betfair_timestamp(&order.placed_date).map_err(|e| anyhow::anyhow!("Failed to parse fill report for {}: {e}", order.bet_id))?;
// after
let ts = if order.placed_date.is_empty() {
ts_init
} else {
parse_betfair_timestamp(&order.placed_date).map_err(|e| anyhow::anyhow!("Failed to parse fill report for {}: {e}", order.bet_id))?
}; Defensive patterns
Strategy: validation
Validate before calling
// guard before report generation
let ts = parse_betfair_timestamp(&order.placed_date)
.inspect_err(|e| tracing::warn!("bet {} bad placed_date {:?}: {e}", order.bet_id, order.placed_date)); Try / catch
match client.generate_fill_reports().await {
Ok(fills) => apply(fills),
Err(e) if e.to_string().contains("Failed to parse fill report") => {
tracing::error!("fill timestamp parse failure: {e:#}");
}
Err(e) => return Err(e),
} Prevention
- Verify expected Betfair timestamp format against real payloads after API upgrades.
- Make parse_betfair_timestamp tolerant of optional fractional seconds.
- Log raw placed_date values on parse failure.
When it happens
Trigger: A Betfair order record has a placed_date string that fails timestamp parsing (wrong format, missing value, unexpected timezone representation) during fill report generation.
Common situations: Betfair changing date serialization; null/empty placed_date on unusual order records; locale-dependent date formats.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid config type for BetfairDataClientFactory. Expected B
- Invalid config type for BetfairExecutionClientFactory. Expec
- OCM state lock poisoned
- Cannot extract market ID from {instrument_id}
- Cannot extract selection ID from {instrument_id}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a4abd3b4bb696b51.
Report an issue: GitHub.