nautechsystems/nautilus_trader · error
Empty `payload` for `delete` '{key}'
Error message
Empty `payload` for `delete` '{key}' What it means
delete_from_index removes a key's value from a set/hash index during a Redis pipeline delete. For set indexes a payload (the member value, e.g. the order or position id bytes) is required; if the caller passes None payload, this error fires. It is an internal invariant: index deletions must always carry the member to remove.
Source
Thrown at crates/infrastructure/src/redis/cache.rs:1082
value.is_some()
);
match collection {
INDEX => delete_from_index(pipe, key, value),
ORDERS | POSITIONS | ACCOUNTS | ACTORS | STRATEGIES => {
delete_string(pipe, key);
Ok(())
}
_ => anyhow::bail!("Unsupported operation: `delete` for collection '{collection}'"),
}
}
fn delete_from_index(
pipe: &mut Pipeline,
key: &str,
value: Option<Vec<Bytes>>,
) -> anyhow::Result<()> {
let value = value.ok_or_else(|| anyhow::anyhow!("Empty `payload` for `delete` '{key}'"))?;
let index_key = get_index_key(key)?;
match index_key {
INDEX_ORDER_IDS
| INDEX_ORDERS
| INDEX_ORDERS_OPEN
| INDEX_ORDERS_CLOSED
| INDEX_ORDERS_EMULATED
| INDEX_ORDERS_INFLIGHT
| INDEX_POSITIONS
| INDEX_POSITIONS_OPEN
| INDEX_POSITIONS_CLOSED => {
remove_from_set(pipe, key, value[0].as_ref());
Ok(())
}
INDEX_ORDER_POSITION | INDEX_ORDER_CLIENT => {
remove_from_hash(pipe, key, value[0].as_ref());
Ok(())View on GitHub (pinned to 18893faf8b)
Solutions
- If you call the cache delete API directly, always provide Some(vec![member_bytes]) as the payload when deleting from an index key.
- Check any custom adapter code that constructs DatabaseCommand objects for Delete operations and ensure payloads are set for index keys.
- Verify the key actually denotes an index; plain record deletes (orders/positions) use None payload legitimately and skip this path.
- Upgrade nautilus_trader if this arises from stock delete_order/delete_position — it would indicate an internal bug.
Example fix
// before let op = DatabaseCommand::new(DatabaseOperation::Delete, index_key, None); // after let op = DatabaseCommand::new(DatabaseOperation::Delete, index_key, Some(vec![member_id_bytes.clone()]));
Defensive patterns
Strategy: validation
Validate before calling
// ensure index deletes always carry a payload assert!(payload.is_some(), "index delete requires member payload");
Type guard
fn has_payload(p: &Option<Vec<Bytes>>) -> bool { p.as_ref().map_or(false, |v| !v.is_empty()) } Prevention
- Always pass Some(vec![member_bytes]) when deleting from an index key.
- Reserve None payloads for record keys, not index keys.
- Review custom DatabaseCommand construction code for missing payloads.
When it happens
Trigger: A delete operation whose key maps to an index (INDEX_ORDER_IDS, INDEX_ORDERS, INDEX_ORDERS_OPEN, etc.) is issued without a payload — i.e. DatabaseCommand::new(Delete, index_key, None) reaches the pipeline builder.
Common situations: Usually triggered by internal code paths or custom integrations that build delete commands manually and omit the payload; not normally hit by end users through delete_order/delete_position, which always supply payloads.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Close command should not be drained
- Flush command should not be drained
- Redis config error: username supplied without password. Eith
- Order invariant violated: first event must be OrderInitializ
- noid '{}' does not match new order oid '{}'
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8894a81e892457c4.
Report an issue: GitHub.