AprilNEA/OpenLogi · error

the selected device has no stable synthetic identity for…

Error message

the selected device has no stable synthetic identity for cassette relationships; rerun with --profile-only

What it means

Cassette files record sanitized identity material (device unit ID and/or serial number) so relationships between cassettes can be verified. `add_model_identities` refuses to proceed when the selected device's `DeviceModelInfo` has an all-zero unit ID and no serial number, because there is no stable identity to anchor cassette relationships; it suggests rerunning with `--profile-only`, which omits cassette capture.

Solutions

  1. Rerun with `--profile-only` as the error suggests — this is the supported mode when no stable identity exists
  2. Re-capture the device profile so the unit ID/serial probe runs again and identity fields are populated
  3. Verify on hardware (`openlogi list` / diagnostics) that the device actually reports a non-zero unit ID or serial; if it never does, the device cannot anchor cassette relationships
  4. Pick a different device/slot that reports stable identity if multiple devices are available

Example fix

// before: full cassette capture with an identity-less device
$ openlogi fixture contribute --id my-fixture --device 1 --output output/my-fixture
Error: the selected device has no stable synthetic identity for cassette relationships; rerun with --profile-only
// after
$ openlogi fixture contribute --id my-fixture --device 1 --output output/my-fixture --profile-only
Defensive patterns

Strategy: validation

Validate before calling

// Before a full capture, confirm the selected model has stable identity
fn has_stable_identity(model: &DeviceModelInfo) -> bool {
    model.unit_id != [0; 4] || model.serial_number.is_some()
}
if !has_stable_identity(&model) {
    eprintln!("no stable identity: use --profile-only");
}

Type guard

fn is_cassette_capable(model: &DeviceModelInfo) -> bool {
    model.unit_id != [0; 4] || model.serial_number.is_some()
}

Try / catch

match contribute_result {
    Err(e) if e.to_string().contains("no stable synthetic identity") => {
        eprintln!("falling back to --profile-only");
        // rerun with args.profile_only = true
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running a full `openlogi fixture contribute` capture when the selected device model reports `unit_id == [0;4]` and `serial_number == None` — e.g. a device that failed identity probing, a cloned/anonymous unit, or a profile snapshot taken before the device reported its identity.

Common situations: Devices whose HID++ identity probe returned zeros (firmware quirk or probe failure); fixtures built from stale profiles captured before a firmware update changed identity reporting; contributing from a mock/test device without identity data; selecting a slot whose device lacks model_info identity fields.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at crates/openlogi-cli/src/cmd/fixture/contribute.rs:379

    route: &DeviceRoute,
    slot: u8,
) -> Result<&'a DeviceModelInfo> {
    profile
        .inventories
        .iter()
        .find(|inventory| {
            inventory.paired.iter().any(|device| {
                DeviceRoute::device_route_for(inventory, device.slot).as_ref() == Some(route)
            })
        })
        .and_then(|inventory| inventory.paired.iter().find(|device| device.slot == slot))
        .and_then(|device| device.model_info.as_ref())
        .ok_or_else(|| anyhow!("selected profile route has no identity-bearing device model"))
}

fn add_model_identities(plan: &mut HidCassetteIdentityPlan, model: &DeviceModelInfo) -> Result<()> {
    if model.unit_id == [0; 4] && model.serial_number.is_none() {
        bail!(
            "the selected device has no stable synthetic identity for cassette relationships; \
             rerun with --profile-only"
        );
    }
    if model.unit_id != [0; 4] {
        plan.insert(SanitizedIdentityKind::DeviceUnitId, model.unit_id.to_vec())?;
    }
    if let Some(serial) = model.serial_number.as_deref() {
        plan.insert(
            SanitizedIdentityKind::DeviceSerialNumber,
            serial.as_bytes().to_vec(),
        )?;
    }
    Ok(())
}

fn require_same_structural_route(expected: &DeviceRoute, actual: &DeviceRoute) -> Result<()> {
    let matches = match (expected, actual) {

View on GitHub (pinned to e846e6f4b4)