{"record":{"id":"e4a6c50d2f535641","repo":"nautechsystems/nautilus_trader","slug":"invalid-nodestate-value","errorCode":null,"errorMessage":"Invalid NodeState value","messagePattern":"Invalid NodeState value","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/live/src/node/state.rs","lineNumber":67,"sourceCode":"    ShuttingDown = 3,\n    Stopped = 4,\n}\n\nimpl NodeState {\n    /// Creates a `NodeState` from its `u8` representation.\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is not a valid `NodeState` discriminant (0-4).\n    #[must_use]\n    pub const fn from_u8(value: u8) -> Self {\n        match value {\n            0 => Self::Idle,\n            1 => Self::Starting,\n            2 => Self::Running,\n            3 => Self::ShuttingDown,\n            4 => Self::Stopped,\n            _ => panic!(\"Invalid NodeState value\"),\n        }\n    }\n\n    /// Returns the `u8` representation of this state.\n    #[must_use]\n    pub const fn as_u8(self) -> u8 {\n        self as u8\n    }\n\n    /// Returns whether the state is `Running`.\n    #[must_use]\n    pub const fn is_running(&self) -> bool {\n        matches!(self, Self::Running)\n    }\n}\n\n/// Determines which lifecycle responsibilities the node owns while running.\n///","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/node/state.rs#L49-L85","documentation":"`NodeState::from_u8` in crates/live/src/node/state.rs converts a raw u8 back into a `NodeState` enum and panics on any value outside 0–4. Valid values are 0=Idle, 1=Starting, 2=Running, 3=ShuttingDown, 4=Stopped. Hitting the panic means a byte that never came from `as_u8` was fed to the deserializer — data corruption, a version/schema mismatch, or hand-crafted input.","triggerScenarios":"Deserializing a persisted/configured node state byte that is >= 5 (or from a different enum version) into NodeState via from_u8; loading a state file written by a newer/older NautilusTrader version with shifted enum ordinals; manually constructing the u8 in scripts or tests.","commonSituations":"Upgrade/downgrade across versions where the NodeState representation changed; corrupted state files or storage; FFI/binding layers (Python/other) passing wrong integers; hand-edited config values.","solutions":["Clamp/validate the incoming u8 before conversion: only pass values produced by `NodeState::as_u8`.","Delete or regenerate the corrupted/legacy persisted state file so the node starts from a valid state.","Wrap the conversion in a checked helper returning Option/Result instead of panicking on unknown bytes."],"exampleFix":"// before\nlet state = NodeState::from_u8(raw_byte); // panics if raw_byte > 4\n\n// after\nlet state = NodeState::try_from_u8(raw_byte) // or:\nlet state = match raw_byte { 0..=4 => NodeState::from_u8(raw_byte), _ => NodeState::Idle };\n// ideally add a checked variant in the crate:\n// pub const fn try_from_u8(v: u8) -> Option<NodeState>","handlingStrategy":"validation","validationCode":"// before deserializing\nif !(0..=4).contains(&raw) { return Err(format!(\"invalid NodeState byte: {raw}\")); }","typeGuard":"fn is_valid_node_state(v: u8) -> bool { v <= 4 }","tryCatchPattern":"// panics are not catchable in Rust; use a checked wrapper:\nfn parse_state(v: u8) -> Option<NodeState> { (v <= 4).then(|| NodeState::from_u8(v)) }","preventionTips":["Only persist/read state bytes produced by NodeState::as_u8 of the same version.","Clear stale state files after upgrading NautilusTrader versions.","Validate externally supplied integers at the FFI/binding boundary before conversion."],"tags":["rust","panic","enum","deserialization","live-node"],"backgroundTag":"invalid-enum-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}