AprilNEA/OpenLogi · error

lumens must be in the supported range

Error message

lumens must be in the supported range {}..={} with step {}

What it means

Raised in `set_brightness` when `--lumens` is given but the value is outside the device's advertised brightness range or the device's range is not expressed in lumens. The CLI validates against `range.contains(lumens)` and `range.unit() == Lumens` before sending a BrightnessNative command, embedding min/max/step in the message.

Solutions

  1. Read the supported range from the error text and pass a value within min..=max honoring step
  2. Use `--percent` instead of `--lumens` for unit-independent brightness control
  3. Check `openlogi list`/device docs for the actual native range before scripting values

Example fix

// before
openlogi light brightness --lumens 500
// after
openlogi light brightness --percent 50
# or use a value inside the advertised range, e.g. min=20 max=200 step=10:
openlogi light brightness --lumens 200
Defensive patterns

Strategy: validation

Validate before calling

let range = &caps.brightness.expect("checked earlier");
if !range.contains(lumens) || range.unit() != LightValueUnit::Lumens {
    anyhow::bail!("lumens {} outside {}..={} step {}", lumens, range.min(), range.max(), range.step());
}

Type guard

fn lumens_in_range(range: &BrightnessRange, v: u32) -> bool {
    range.unit() == LightValueUnit::Lumens && range.contains(v)
}

Try / catch

match set_brightness(args).await {
    Ok(()) => (),
    Err(e) if e.to_string().contains("supported range") => {
        eprintln!("{}\nUse --percent instead for unit-safe control.", e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: `openlogi light ... brightness --lumens N` where N < range.min(), N > range.max(), N violates range.step(), or the device's brightness range uses a different unit than lumens.

Common situations: Guessing lumen values instead of reading the device's advertised range from the error message; confusing percent vs native lumen interfaces; typos like 1000 instead of 100.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13). Data as JSON: /api/errors/1ff7f5f63bdd5d06. Report an issue: GitHub.

Appendix: source

Thrown at crates/openlogi-cli/src/cmd/light.rs:131

    let devices = standalone().await?;
    let device = select(&devices, query)?;
    apply(device, LightCommand::Power(enabled)).await
}

async fn set_brightness(args: BrightnessArgs) -> Result<()> {
    let devices = standalone().await?;
    let device = select(&devices, args.device.device.as_deref())?;
    let caps = device
        .light_capabilities
        .ok_or_else(|| anyhow!("selected light did not advertise capabilities"))?;
    let range = caps
        .brightness
        .ok_or_else(|| anyhow!("selected light does not support brightness"))?;
    let command = match (args.percent, args.lumens) {
        (Some(percent), None) => LightCommand::BrightnessPercent(percent),
        (None, Some(lumens)) => {
            if range.unit() != LightValueUnit::Lumens || !range.contains(lumens) {
                return Err(anyhow!(
                    "lumens must be in the supported range {}..={} with step {}",
                    range.min(),
                    range.max(),
                    range.step()
                ));
            }
            LightCommand::BrightnessNative(lumens)
        }
        (None, None) => return Err(anyhow!("pass either --percent or --lumens")),
        (Some(_), Some(_)) => unreachable!("clap enforces the argument conflict"),
    };
    apply(device, command).await
}

async fn set_temperature(args: TemperatureArgs) -> Result<()> {
    let devices = standalone().await?;
    let device = select(&devices, args.device.device.as_deref())?;
    apply(device, LightCommand::TemperatureKelvin(args.kelvin)).await

View on GitHub (pinned to e846e6f4b4)