{"record":{"id":"039b623901efc1f7","repo":"AprilNEA/OpenLogi","slug":"could-not-derive-synthetic-unifying-serial","errorCode":null,"errorMessage":"could not derive synthetic Unifying serial","messagePattern":"could not derive synthetic Unifying serial","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/contribute.rs","lineNumber":341,"sourceCode":") -> Result<HidCassetteIdentityPlan> {\n    let mut plan = HidCassetteIdentityPlan::default();\n    let model = match selected_route {\n        DeviceRoute::Bolt { receiver_uid, slot } => {\n            plan.insert(\n                SanitizedIdentityKind::ReceiverUniqueId,\n                receiver_uid.as_bytes().to_vec(),\n            )?;\n            selected_model(profile, selected_route, *slot)?\n        }\n        DeviceRoute::Unifying { receiver_uid, slot } => {\n            let ordinal = classify_synthetic_profile_identity(\n                SyntheticIdentityKind::UnifyingReceiverRoute,\n                receiver_uid,\n            )?;\n            let serial =\n                generate_synthetic_identity(SyntheticIdentityKind::UnifyingReceiverSerial, ordinal)\n                    .as_bytes()\n                    .ok_or_else(|| anyhow!(\"could not derive synthetic Unifying serial\"))?\n                    .to_vec();\n            plan.insert(SanitizedIdentityKind::ReceiverSerialNumber, serial)?;\n            selected_model(profile, selected_route, *slot)?\n        }\n        DeviceRoute::Direct { .. } => selected_model(\n            profile,\n            selected_route,\n            openlogi_core::hid::DIRECT_DEVICE_INDEX,\n        )?,\n        DeviceRoute::RawHid { .. } => {\n            bail!(\"raw-HID devices support profile-only contributions\")\n        }\n    };\n    add_model_identities(&mut plan, model)?;\n    Ok(plan)\n}\n\nfn selected_model<'a>(","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/contribute.rs#L323-L359","documentation":"Thrown by `identity_plan` while building the sanitized identity plan for a receiver-routed fixture: `generate_synthetic_identity(SyntheticIdentityKind::UnifyingReceiverSerial, ordinal).as_bytes()` returned `None`, so no synthetic serial bytes could be derived for the receiver serial number. The generator is expected to produce bytes for every kind/ordinal, so this signals that the synthetic-identity policy refused or cannot encode this input — an internal invariant rather than user error.","triggerScenarios":"Running the fixture contribute flow for a `DeviceRoute::Receiver`-style profile where the identity generator returns no byte representation for the given `SyntheticIdentityKind::UnifyingReceiverSerial` and ordinal — e.g. an ordinal outside the range the policy encodes, or a policy/derive mismatch after a fixture-crate change.","commonSituations":"Contributing fixtures with a hand-edited or out-of-range device ordinal; running a newer CLI against an older `openlogi-fixture` policy (or vice versa) where the serial kind lost its byte encoding; a regression in the synthetic-identity policy.","solutions":["Check the ordinal passed into `identity_plan` is within the range `openlogi-fixture`'s synthetic identity policy supports, and use a valid one.","Verify `openlogi-cli` and `openlogi-fixture` versions are from the same workspace/build — regenerate with a consistent build.","Inspect `generate_synthetic_identity` for `UnifyingReceiverSerial`: if `as_bytes()` is None by design for some inputs, fix the caller's input or extend the policy.","If reproducible with a stock ordinal, file/fix it as a bug — this path should be unreachable for valid inputs."],"exampleFix":"// before: as_bytes() can be None, error surfaces here\nlet serial = generate_synthetic_identity(SyntheticIdentityKind::UnifyingReceiverSerial, ordinal)\n    .as_bytes()\n    .ok_or_else(|| anyhow!(\"could not derive synthetic Unifying serial\"))?\n    .to_vec();\n// after: assert the invariant with context for diagnosis\nlet serial = generate_synthetic_identity(SyntheticIdentityKind::UnifyingReceiverSerial, ordinal)\n    .as_bytes()\n    .with_context(|| format!(\"synthetic Unifying serial undefined for ordinal {ordinal}\"))?\n    .to_vec();","handlingStrategy":"try-catch","validationCode":"// verify the ordinal is inside the policy's supported range before deriving\nlet ordinal = profile_ordinal(profile)?;\nassert!(ordinal < openlogi_fixture::MAX_SYNTHETIC_ORDINAL,\n    \"ordinal {ordinal} exceeds synthetic identity policy range\");","typeGuard":null,"tryCatchPattern":"match identity_plan(profile, route, ordinal) {\n    Err(e) if msg_contains(&e, \"could not derive synthetic Unifying serial\") => {\n        eprintln!(\"identity policy cannot encode ordinal {ordinal}; \\\n                   check openlogi-fixture version and ordinal range\");\n        std::process::exit(1);\n    }\n    other => other?,\n}","preventionTips":["Keep `openlogi-cli` and `openlogi-fixture` built from the same workspace — no version skew.","Don't hand-edit fixture profile ordinals; let the contribute flow assign them.","After upgrading, re-derive identity plans rather than reusing cached ones.","Treat this error as a bug report trigger — valid ordinals should never fail."],"tags":["cli","fixtures","synthetic-identity","invariant"],"backgroundTag":"internal-invariant-violation","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"}