nautechsystems/nautilus_trader · error · PyValueError
Invalid BybitPositionMode value: {int_val}
Error message
Invalid BybitPositionMode value: {int_val} What it means
The Python binding for BybitPositionMode converts incoming API payload integers to enum variants: only 0 (MergedSingle) and 3 (BothSides) are accepted. Any other integer, or an unrecognized variant-name string, raises this error.
Source
Thrown at crates/adapters/bybit/src/python/enums.rs:298
pub fn value(&self) -> i32 {
*self as i32
}
#[staticmethod]
#[must_use]
fn variants() -> Vec<String> {
Self::iter().map(|x| x.to_string()).collect()
}
#[classmethod]
#[pyo3(name = "from_str")]
fn py_from_str(_cls: &Bound<'_, PyType>, data: &Bound<'_, PyAny>) -> PyResult<Self> {
// Try to extract as integer first (for API payloads that send 0 or 3)
if let Ok(int_val) = data.extract::<i32>() {
return match int_val {
0 => Ok(Self::MergedSingle),
3 => Ok(Self::BothSides),
_ => Err(to_pyvalue_err(anyhow::anyhow!(
"Invalid BybitPositionMode value: {int_val}"
))),
};
}
// Fall back to string parsing for variant names
let data_str: String = data.str()?.extract()?;
Self::from_str(&data_str).map_err(to_pyvalue_err)
}
}
#[pymethods]
#[pyo3_stub_gen::derive::gen_stub_pymethods]
impl BybitPositionIdx {
/// Position index values used for hedge mode payloads.
#[new]
fn py_new(py: Python<'_>, value: &Bound<'_, PyAny>) -> PyResult<Self> {
let t = Self::type_object(py);View on GitHub (pinned to 18893faf8b)
Solutions
- Use 0 for MergedSingle (one-way) or 3 for BothSides (hedge mode) in integer payloads
- Pass exact variant names as strings: 'MergedSingle' or 'BothSides'
- Check the Bybit account/position-mode API response for unexpected values and update the adapter if Bybit added new modes
Example fix
// before: wrong integer mapping mode = BybitPositionMode.from_str(1) // after mode = BybitPositionMode.from_str(3) # BothSides (hedge mode)
Defensive patterns
Strategy: type-guard
Validate before calling
if isinstance(v, int) and v not in (0, 3):
raise ValueError(f'position mode must be 0 (MergedSingle) or 3 (BothSides), got {v}') Type guard
def is_valid_position_mode(v) -> bool:
return v in (0, 3) or str(v) in ('MergedSingle', 'BothSides') Try / catch
try:
mode = BybitPositionMode.from_str(raw)
except ValueError as e:
log.warning('bad position mode %r', raw); mode = BybitPositionMode.MergedSingle Prevention
- Use the documented integer mapping 0/3 only
- Prefer variant-name strings in hand-written config
- Centralize mode parsing in one helper
When it happens
Trigger: Deserializing a Bybit position-mode value from a payload where the integer is not 0 or 3 (e.g. 1 or 2), or passing an invalid string to BybitPositionMode.from_str in Python.
Common situations: Feeding values from another exchange's position-mode encoding; Bybit docs/versions using a different integer mapping; hand-written config using 'hedge' instead of 'BothSides'.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid BybitPositionIdx value: {int_val}
- Invalid NodeState value
- Timedelta not supported for aggregation type: {:?}
- Invalid `ConnectionMode` value: {value}
- Unsupported SBE execution type: {et}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ee5d8eaa286f6324.
Report an issue: GitHub.