{"record":{"id":"0af57ac4c255c27b","repo":"AprilNEA/OpenLogi","slug":"pass-either-percent-or-lumens","errorCode":null,"errorMessage":"pass either --percent or --lumens","messagePattern":"pass either --percent or --lumens","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/openlogi-cli/src/cmd/light.rs","lineNumber":140,"sourceCode":"        .light_capabilities\n        .ok_or_else(|| anyhow!(\"selected light did not advertise capabilities\"))?;\n    let range = caps\n        .brightness\n        .ok_or_else(|| anyhow!(\"selected light does not support brightness\"))?;\n    let command = match (args.percent, args.lumens) {\n        (Some(percent), None) => LightCommand::BrightnessPercent(percent),\n        (None, Some(lumens)) => {\n            if range.unit() != LightValueUnit::Lumens || !range.contains(lumens) {\n                return Err(anyhow!(\n                    \"lumens must be in the supported range {}..={} with step {}\",\n                    range.min(),\n                    range.max(),\n                    range.step()\n                ));\n            }\n            LightCommand::BrightnessNative(lumens)\n        }\n        (None, None) => return Err(anyhow!(\"pass either --percent or --lumens\")),\n        (Some(_), Some(_)) => unreachable!(\"clap enforces the argument conflict\"),\n    };\n    apply(device, command).await\n}\n\nasync fn set_temperature(args: TemperatureArgs) -> Result<()> {\n    let devices = standalone().await?;\n    let device = select(&devices, args.device.device.as_deref())?;\n    apply(device, LightCommand::TemperatureKelvin(args.kelvin)).await\n}\n\nasync fn apply(device: &StandaloneDevice, command: LightCommand) -> Result<()> {\n    let model = find_litra(\n        device.address.vendor_id,\n        device.address.product_id,\n        device.address.usage_page,\n        device.address.usage_id,\n    )","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/light.rs#L122-L158","documentation":"Raised in `set_brightness` when neither `--percent` nor `--lumens` is supplied, so no brightness value can be built. The complementary case (both flags at once) is unreachable because clap enforces the argument conflict at parse time, so this error is the only real missing-argument path.","triggerScenarios":"Running the brightness subcommand with no value flag at all, e.g. `openlogi light brightness` — clap accepts it (the flags are individually optional) and the command handler bails.","commonSituations":"Forgetting the flag in scripts; copying a command line and dropping the value; assuming a default brightness exists (there is none by design).","solutions":["Add either `--percent <0-100>` or `--lumens <value>` to the brightness command","If scripting, default the value explicitly (e.g. `--percent 50`) instead of omitting it","Note that passing both flags is rejected earlier by clap's conflict rule — pick exactly one"],"exampleFix":"// before\nopenlogi light brightness --device \"MX Mouse\"\n// after\nopenlogi light brightness --device \"MX Mouse\" --percent 60","handlingStrategy":"validation","validationCode":"if args.percent.is_none() && args.lumens.is_none() {\n    anyhow::bail!(\"pass either --percent or --lumens\");\n}","typeGuard":"fn has_brightness_value(args: &BrightnessArgs) -> bool {\n    args.percent.is_some() ^ args.lumens.is_some()\n}","tryCatchPattern":"match set_brightness(args).await {\n    Ok(()) => (),\n    Err(e) if e.to_string().contains(\"pass either\") => {\n        eprintln!(\"Usage: openlogi light brightness --percent <0-100> | --lumens <n>\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Make one flag required in clap (group with `required(true)`) so the shell errors early","Always pass an explicit brightness value in scripts; never rely on defaults","Document the flag pair in the subcommand's about text"],"tags":["cli","arguments","lighting"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8","analyzedAt":"2026-09-13T03:07:16.451Z","contentChangedAt":"2026-09-13T03:07:16.451Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}