nautechsystems/nautilus_trader · error
Serialized account event has no balances
Error message
Serialized account event has no balances
What it means
After serializing the AccountState to a JSON value, add_account requires a "balances" key to bind into the account_event table. This error means the serialized object contained no "balances" field — the AccountState struct's serde representation lacks that key (skipped via #[serde(skip)] or renamed) or serialized to a non-object shape.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:1114
if updated {
let exists =
Self::check_if_account_event_exists(pool, account_event.account_id).await?;
if !exists {
anyhow::bail!(
"Account event does not exist for account: {}",
account_event.account_id
);
}
}
let mut transaction = pool.begin().await?;
let event = serde_json::to_value(&account_event)
.map_err(|e| anyhow::anyhow!("Failed to serialize account event: {e}"))?;
let balances = event
.get("balances")
.cloned()
.ok_or_else(|| anyhow::anyhow!("Serialized account event has no balances"))?;
let margins = event
.get("margins")
.cloned()
.ok_or_else(|| anyhow::anyhow!("Serialized account event has no margins"))?;
sqlx::query(
r#"
INSERT INTO "account" (id) VALUES ($1) ON CONFLICT (id) DO NOTHING
"#,
)
.bind(account_event.account_id.to_string())
.execute(&mut *transaction)
.await
.map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to insert into account table: {e}"))?;
sqlx::query(r#"
INSERT INTO "account_event" (View on GitHub (pinned to 18893faf8b)
Solutions
- Print or log serde_json::to_value(&account_event) keys to see what fields actually exist.
- Confirm you are constructing a genuine AccountState from this crate version whose Serialize includes "balances"; rebuild the crate if binaries are stale.
- Remove any #[serde(skip_serializing_if)] or rename on the balances field, or pass an explicit empty Vec instead of skipping.
- If balances are legitimately absent, persist an empty JSON array rather than omitting the field.
Example fix
// before: field skipped when empty #[serde(skip_serializing_if = "Vec::is_empty")] pub balances: Vec<AccountBalance>, // after: always serialize the key pub balances: Vec<AccountBalance>,
Defensive patterns
Strategy: validation
Validate before calling
// confirm the serialized event carries balances
let json = serde_json::to_value(&account_event)?;
assert!(json.get("balances").is_some(), "AccountState serialization missing 'balances'"); Type guard
fn has_balances(state: &AccountState) -> bool {
serde_json::to_value(state)
.ok()
.and_then(|v| v.get("balances").cloned())
.is_some()
} Try / catch
match add_account(&pool, updated, state).await {
Err(e) if e.to_string().contains("no balances") => {
log::error!("event type lost its balances field — check serde attrs/versions");
}
other => other?,
} Prevention
- Do not add skip_serializing_if to required fields on account events.
- Rebuild after upgrading NautilusTrader so struct and schema stay in sync.
- Persist empty Vecs instead of omitting empty collections.
- Assert required keys exist in a serialization unit test.
When it happens
Trigger: add_account receives an AccountState whose Serialize impl omits the balances field — e.g. a custom/renamed serde attribute, a subclassed or hand-rolled event type, or an empty balances vector serialized as a skipped/None field.
Common situations: Upgrading NautilusTrader while a cached/stale build still expects the old field name; using a custom AccountState-like type with #[serde(skip_serializing_if)] on balances; deserializing then re-serializing events through a lossy intermediate format that dropped the key.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Serialized account event has no margins
- No currency_code in account details
- Failed to serialize account event: {e}
- Failed to insert into account table: {e}
- Failed to insert into account_event table: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/0a580582a4d7a421.
Report an issue: GitHub.