{"record":{"id":"ee9607f93c9d1d3d","repo":"linera-io/linera-protocol","slug":"bulk-height-range-from-must-not-exceed-to","errorCode":null,"errorMessage":"--bulk-height-range FROM must not exceed TO","messagePattern":"--bulk-height-range FROM must not exceed TO","errorType":"validation","errorClass":"anyhow","httpStatus":null,"severity":"warning","filePath":"linera-service/src/cli/validator_benchmark/bulk_download.rs","lineNumber":179,"sourceCode":"        certs_per_sec: certs_received as f64 / duration,\n        latency_ms: samples.summary(),\n    }\n}\n\n/// Resolve the height range: `auto` targets the most recent\n/// `batch_size * AUTO_BATCH_COUNT` heights up to the tip; otherwise `FROM:TO`.\nfn resolve_range(arg: &str, tip: u64, batch_size: u32) -> Result<(u64, u64)> {\n    if arg == \"auto\" {\n        let span = batch_size as u64 * AUTO_BATCH_COUNT;\n        Ok((tip.saturating_sub(span), tip))\n    } else {\n        let (a, b) = arg\n            .split_once(':')\n            .ok_or_else(|| anyhow::anyhow!(\"--bulk-height-range must be `auto` or `FROM:TO`\"))?;\n        let from: u64 = a.trim().parse()?;\n        let to: u64 = b.trim().parse()?;\n        if to < from {\n            anyhow::bail!(\"--bulk-height-range FROM must not exceed TO\");\n        }\n        Ok((from, to))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::resolve_range;\n\n    #[test]\n    fn auto_under_tip() {\n        assert_eq!(\n            resolve_range(\"auto\", 50_000, 100).unwrap(),\n            (40_000, 50_000)\n        );\n    }\n\n    #[test]","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-service/src/cli/validator_benchmark/bulk_download.rs#L161-L197","documentation":"`resolve_range` parses the `--bulk-height-range FROM:TO` argument for the validator benchmark's bulk-download layer. Both endpoints are parsed as u64 and the run bails when TO is numerically smaller than FROM, i.e. the block-height window is inverted. The alternative form `auto` targets the most recent `batch_size * AUTO_BATCH_COUNT` heights up to the tip and never hits this check.","triggerScenarios":"Passing an inverted explicit range such as `--bulk-height-range 200:100` (from=200, to=100) to the validator benchmark's bulk download.","commonSituations":"Assuming the pair is (newest:oldest) or (to:from); scripts computing the range around the chain tip and swapping the bounds on short chains; copy-paste from height-output where the newest height is printed first.","solutions":["Swap the endpoints so the lower height comes first: `--bulk-height-range 100:200`","Use `--bulk-height-range auto` to target recent heights automatically without computing bounds","In scripts, sort the two heights (or validate `from <= to`) before composing the flag"],"exampleFix":"# before\nlinera validator benchmark <addr> --chain <id> --bulk-height-range 200:100\n\n# after\nlinera validator benchmark <addr> --chain <id> --bulk-height-range 100:200","handlingStrategy":"validation","validationCode":"// Validate/normalize before passing the flag.\nfn normalize_range(from: u64, to: u64) -> anyhow::Result<(u64, u64)> {\n    if from > to {\n        Ok((to, from)) // or reject: bail!(\"inverted height range {from}:{to}\")\n    } else {\n        Ok((from, to))\n    }\n}\nlet (from, to) = normalize_range(from_height, to_height)?;\nlet flag = format!(\"--bulk-height-range {from}:{to}\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer `--bulk-height-range auto` unless you need a specific window","In scripts, derive FROM/TO from a single tip value (tip - n, tip) so they cannot be swapped","Remember the format is FROM:TO with FROM inclusive and lower-or-equal"],"tags":["validator-benchmark","argument-validation","linera-cli"],"backgroundTag":"invalid-argument-range","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}