{"record":{"id":"139da2fbf57a8b84","repo":"stalwartlabs/stalwart","slug":"node-id-node-id-exceeds-max-node-id-panicking","errorCode":null,"errorMessage":"Node id {node_id} exceeds {MAX_NODE_ID}, panicking to avoid data corruption","messagePattern":"Node id (.+?) exceeds (.+?), panicking to avoid data corruption","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/common/src/config/inner.rs","lineNumber":53,"sourceCode":"    cache::{Cache, CacheWithTtl},\n    snowflake::{MAX_NODE_ID, SnowflakeIdGenerator},\n    tls::build_tls_connector,\n};\n\nimpl Data {\n    pub async fn parse(bp: &mut Bootstrap) -> Self {\n        // Parse certificates\n        let mut certificates = AHashMap::new();\n        let mut subject_names = AHashSet::new();\n        parse_certificates(bp, &mut certificates, &mut subject_names).await;\n        if subject_names.is_empty() {\n            subject_names.insert(\"localhost\".into());\n        }\n\n        // Build and test snowflake id generator\n        let node_id = bp.node_id();\n        if node_id > MAX_NODE_ID {\n            panic!(\"Node id {node_id} exceeds {MAX_NODE_ID}, panicking to avoid data corruption\");\n        }\n        SnowflakeIdGenerator::set_node_id(node_id as u64);\n        let id_generator = SnowflakeIdGenerator::new();\n        if !id_generator.is_valid() {\n            panic!(\"Invalid system time, panicking to avoid data corruption\");\n        }\n\n        // Initialize apps\n        let applications = WebApplications::new();\n        applications.reload(bp).await;\n\n        let blocked_ips = BlockedIps::parse(bp).await;\n        let lookup_stores = LookupStores::build(bp).await;\n\n        Data {\n            spam_classifier: ArcSwap::from_pointee(SpamClassifier::default()),\n            tls_certificates: ArcSwap::from_pointee(certificates),\n            tls_self_signed_cert: build_self_signed_cert(","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/stalwartlabs/stalwart/blob/e96200385781a6a9995a8b839ac27d6c75a983ee/crates/common/src/config/inner.rs#L35-L71","documentation":"At config parse time the server builds a snowflake ID generator and installs a node id taken from the validated config. Snowflake ids embed the node id, and exceeding MAX_NODE_ID would make ids collide or overflow across cluster nodes, corrupting data. The code deliberately panics rather than starting with an unsafe node id, warning that this is to avoid data corruption.","triggerScenarios":"Setting a `node-id` (or cluster node id) value in the server configuration that is greater than MAX_NODE_ID (the bitmask capacity of the snowflake layout, e.g. >1023 for a 10-bit node field). `Config::parse` panics during startup.","commonSituations":"Operators hard-code large node ids when scripting multi-node deployments (e.g. using instance numbers past the limit), or misconfigure a numeric field intended to be small, or reuse a generator config from another product with a wider node field.","solutions":["Lower the configured node id to a value within range (0..=MAX_NODE_ID, per the message) and restart.","If automating deployment, map instance numbers into the valid range (e.g. modulo 1024) before assigning node ids.","Ensure each node still gets a unique in-range id to preserve snowflake uniqueness."],"exampleFix":"# before (config.toml)\nnode-id = 4096\n# after\nnode-id = 7","handlingStrategy":"validation","validationCode":"const MAX_NODE_ID: u32 = 1023; // match the snowflake layout\nlet node_id = config.node_id();\nif node_id > MAX_NODE_ID {\n    eprintln!(\"node-id {node_id} exceeds {MAX_NODE_ID}\");\n    std::process::exit(2);\n}","typeGuard":"fn valid_node_id(v: u32) -> Option<u32> { (v <= 1023).then_some(v) }","tryCatchPattern":"// it is a startup panic, not catchable; validate config before launch:\n// wrap server start in a supervisor that surfaces the panic and exits non-zero","preventionTips":["Cap generated node ids at the snowflake node-field width in deployment tooling.","Document the valid node-id range next to the config sample.","Assign unique in-range ids per node to preserve id uniqueness."],"tags":["config","snowflake-id","startup","rust"],"backgroundTag":"value-out-of-range","analyzedSha":"e96200385781a6a9995a8b839ac27d6c75a983ee","analyzedAt":"2026-09-06T22:07:17.982Z","contentChangedAt":"2026-09-06T22:07:17.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}