nautechsystems/nautilus_trader · error
Order denied: invalid status for {}, expected INITIALIZED
Error message
Order denied: invalid status for {}, expected INITIALIZED What it means
submit_order_native only accepts orders whose status is INITIALIZED. If an order with any other lifecycle status (e.g. SUBMITTED, DENIED, FILLED) is passed again, the submission is denied with this error to prevent duplicate or stale submissions. Orders are meant to flow through this path exactly once.
Source
Thrown at crates/trading/src/strategy/mod.rs:2335
pub(super) fn submit_order_native<T>(
strategy: &mut T,
order: &OrderAny,
position_id: Option<PositionId>,
client_id: Option<ClientId>,
params: Option<Params>,
) -> anyhow::Result<()>
where
T: Strategy + StrategyNative + ?Sized,
{
let core = StrategyNative::strategy_core_mut(strategy);
let trader_id = registered_trader_id(core)?;
let strategy_id = registered_strategy_id(core)?;
let ts_init = core.clock_mut().timestamp_ns();
if order.status() != OrderStatus::Initialized {
anyhow::bail!(
"Order denied: invalid status for {}, expected INITIALIZED",
order.client_order_id()
);
}
let market_exit_tag = core.market_exit_tag;
let is_market_exit_order = order
.tags()
.is_some_and(|tags| tags.contains(&market_exit_tag));
let should_deny_for_market_exit =
core.is_exiting && !order.is_reduce_only() && !is_market_exit_order;
if should_deny_for_market_exit {
strategy.deny_order(order, Ustr::from("MARKET_EXIT_IN_PROGRESS"));
return Ok(());
}
let core = StrategyNative::strategy_core_mut(strategy);View on GitHub (pinned to 18893faf8b)
Solutions
- Only call submit_order_native once per order, immediately after construction while status is INITIALIZED
- Check order.status() before submitting and create a new order for retries
- Trace why the order's status already changed (e.g. an earlier submit, deny, or event application)
Example fix
// before
strategy.submit_order_native(&order)?;
// after
if order.status() == OrderStatus::Initialized {
strategy.submit_order_native(&order)?;
} else {
// create a new order for resubmission
} Defensive patterns
Strategy: validation
Validate before calling
// Rust
if order.status() != OrderStatus::Initialized {
// create a new order instead of resubmitting
} Try / catch
// Rust
match res {
Err(e) if e.to_string().contains("expected INITIALIZED") => {
log::warn!("order already submitted; build a new order for retry");
}
other => other?,
} Prevention
- Submit each order exactly once, immediately after construction
- Never reuse order objects across retries; construct a fresh order with a new client_order_id
- Track submission state in your strategy so a failure path cannot resubmit the same instance
When it happens
Trigger: Calling submit_order_native (via binding_submit_order) with an order object that was already submitted, denied, or otherwise transitioned away from OrderStatus::Initialized.
Common situations: Retrying a submission after a failure without creating a fresh order; submitting the same order instance from multiple code paths; reusing a cached order after a strategy restart.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- cannot cancel Lighter order {}: venue order_id not yet known
- {FAILED}: {e}
- dYdX WebSocket stream task is already registered
- Interactive Brokers only accepts a quote quantity (`cash_qty
- default client already registered
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/2d220b5e616410ea.
Report an issue: GitHub.