nautechsystems/nautilus_trader · error
Portfolio message has empty currency code
Error message
Portfolio message has empty currency code
What it means
parse_portfolio_to_account_state converts a Deribit portfolio update into an AccountState keyed by currency. A portfolio message with a blank currency string cannot identify the asset, so it is rejected.
Source
Thrown at crates/adapters/deribit/src/common/parse.rs:697
/// subscription channel into Nautilus account state events.
///
/// # Returns
///
/// An `AccountState` containing balances and margin information.
///
/// # Errors
///
/// Returns an error if Money conversion fails for any balance field.
pub fn parse_portfolio_to_account_state(
portfolio: &DeribitPortfolioMsg,
account_id: AccountId,
ts_init: UnixNanos,
) -> anyhow::Result<AccountState> {
let ccy_str = portfolio.currency.trim();
// Skip empty currency codes
if ccy_str.is_empty() {
anyhow::bail!("Portfolio message has empty currency code");
}
let currency = Currency::get_or_create_crypto_with_context(
ccy_str,
Some("DERIBIT - Parsing portfolio update"),
);
// See `parse_account_state` for the rationale: cross-margin uses equity and
// `available_withdrawal_funds` (per-currency consistency, conservative free balance);
// segregated uses `margin_balance` and `available_funds` (per-currency scoped).
let is_cross_margin = portfolio.cross_collateral_enabled.unwrap_or(false);
let (total, free) = if is_cross_margin {
(
portfolio.equity,
portfolio
.available_withdrawal_funds
.unwrap_or(Decimal::ZERO),
)View on GitHub (pinned to 18893faf8b)
Solutions
- Skip or log the message instead of hard-failing the stream
- Validate the Deribit payload schema; update the client model if Deribit changed it
- Check for upstream Deribit issues affecting portfolio channel
Example fix
// before
if ccy_str.is_empty() {
anyhow::bail!("Portfolio message has empty currency code");
}
// after
if ccy_str.is_empty() {
log::debug!("Skipping portfolio message with empty currency");
return Ok(None); // or continue
} Defensive patterns
Strategy: try-catch
Validate before calling
if portfolio.currency.trim().is_empty() {
// skip message before parsing
return Ok(());
} Type guard
fn has_currency(p: &DeribitPortfolio) -> bool { !p.currency.trim().is_empty() } Try / catch
match parse_portfolio_to_account_state(&portfolio, ts_init) {
Err(e) if e.to_string().contains("empty currency code") => {
debug!("ignoring empty portfolio update");
}
other => other?,
} Prevention
- Sanity-check websocket payloads before parsing
- Watch for Deribit API schema changes in portfolio messages
- Skip-and-log non-conforming messages to keep streams alive
When it happens
Trigger: Deribit sends a portfolio message whose currency field is empty or whitespace-only after trimming.
Common situations: Malformed/empty Deribit websocket payloads, API schema changes, upstream bugs in portfolio snapshot construction.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- {FAILED}: {e}
- Missing option_type for option instrument
- Invalid trade direction: {other}
- Chart data status is '{}', expected 'ok'
- Unsupported Deribit resolution: {resolution}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d1a4298cd9d92ae9.
Report an issue: GitHub.