AprilNEA/OpenLogi · error

could not pick a device automatically. online devices

Error message

could not pick a device automatically.
  online devices:
{list}
  pass --device <name> to choose one.

What it means

Thrown by `no_match_err` when no `--device` query was given and automatic selection cannot proceed because the online candidate list does not resolve to a single device. The error prints all online devices and tells the user to pass `--device <name>`. This is the ambiguous-selection branch, distinct from the empty-list and query-mismatch branches.

Solutions

  1. Add `--device <name>` choosing one of the names printed in the error's `online devices:` list.
  2. If multiple routes expose the same device, pick the specific route/name combination you intend.
  3. In scripts, always pass `--device` explicitly rather than relying on automatic selection.
  4. Take the other devices offline (or unplug the receiver) if you truly want auto-selection.

Example fix

// before
$ openlogi diag smartshift
// error: could not pick a device automatically...
// after
$ openlogi diag smartshift --device "MX Master 3S"
Defensive patterns

Strategy: validation

Validate before calling

// require --device when more than one candidate is online
let devices = enumerate_candidates()?;
if devices.len() > 1 && query.is_none() {
    eprintln!("multiple devices online; pass --device: {}",
        devices.iter().map(|d| d.name.as_str()).collect::<Vec<_>>().join(", "));
    std::process::exit(2);
}

Try / catch

// auto-pick only when unambiguous, else surface the same guidance
match select_device(&devices, None) {
    Ok(d) => run(d),
    Err(e) => { eprintln!("{e:#}"); std::process::exit(2); } // usage error, user must pass --device
}

Prevention

When it happens

Trigger: Running a diagnostic subcommand without `--device` while multiple HID++ devices are online and the automatic selection logic cannot disambiguate (the list is non-empty, so it is never the empty branch).

Common situations: A mouse and a keyboard both online; a device reachable via both receiver and direct-Bluetooth routes producing multiple candidates; scripted use that assumed exactly one device would be attached.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at crates/openlogi-cli/src/cmd/diag.rs:94

            out.push(Candidate { route, name });
        }
    }
    Ok(out)
}

/// Build a helpful "couldn't pick a device" error that lists what *is* online.
fn no_match_err(devices: &[Candidate], query: Option<&str>) -> anyhow::Error {
    if devices.is_empty() {
        return anyhow!("no online HID++ device found — is a Logi device paired and awake?");
    }
    let list = devices
        .iter()
        .map(|c| format!("    - {} ({})", c.name, c.route))
        .collect::<Vec<_>>()
        .join("\n");
    match query {
        Some(q) => anyhow!("no online device matches `--device {q}`.\n  online devices:\n{list}"),
        None => anyhow!(
            "could not pick a device automatically.\n  online devices:\n{list}\n  \
             pass --device <name> to choose one."
        ),
    }
}

/// Pick the device a diag should run against.
///
/// Selection order:
/// 1. If `query` is set, the first online device whose name contains it
///    (case-insensitive) — lets the user disambiguate explicitly.
/// 2. Else, if `required_features` is non-empty, the first online device whose
///    HID++ feature table exposes *any* of them. This is what stops a
///    mouse-only diag (DPI, SmartShift) from picking a paired keyboard when
///    several devices are online — a real hazard on Bluetooth-direct setups
///    where each device enumerates as its own inventory.
/// 3. Else, the first online device (the original behaviour).
pub(crate) async fn select_device(

View on GitHub (pinned to e846e6f4b4)