{"record":{"id":"e6e56020d1506750","repo":"AprilNEA/OpenLogi","slug":"count-sanitized-channel-candidates-reproduced-the-capture","errorCode":null,"errorMessage":"{count} sanitized channel candidates reproduced the capture; target channel resolution is ambiguous, so no fixture was written","messagePattern":"(.+?) sanitized channel candidates reproduced the capture; target channel resolution is ambiguous, so no fixture was written","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs","lineNumber":62,"sourceCode":"    let Ok(backend) = ReplayBackend::new(topology, vec![candidate.cassette.clone()]) else {\n        return false;\n    };\n    let replayed = operation.observe(&backend, &route).await;\n    replayed.ensure_replayable().is_ok()\n        && replayed == *captured\n        && backend.require_complete().is_ok()\n}\n\nfn require_single_passing_candidate(\n    mut candidates: Vec<SanitizedCandidate>,\n) -> Result<SanitizedCandidate> {\n    match candidates.len() {\n        1 => Ok(candidates.remove(0)),\n        0 => bail!(\n            \"no sanitized channel candidate reproduced the captured semantic observation and \\\n             completed strict replay; no fixture was written\"\n        ),\n        count => bail!(\n            \"{count} sanitized channel candidates reproduced the capture; target channel \\\n             resolution is ambiguous, so no fixture was written\"\n        ),\n    }\n}\n\nfn replay_topology(\n    target: &TargetCandidate,\n    route: &DeviceRoute,\n    cassette: &HidCassette,\n) -> ReplayTopology {\n    let receiver_slots = match route {\n        DeviceRoute::Bolt { slot, .. } | DeviceRoute::Unifying { slot, .. } => {\n            vec![ReceiverSlot {\n                slot: *slot,\n                state: ReceiverSlotState::Paired(ReceiverLinkState::Online),\n            }]\n        }","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs#L44-L80","documentation":"`require_single_passing_candidate` requires a unique passing sanitized channel candidate; when more than one candidate reproduces the capture, the target channel is ambiguous and writing a fixture would bake in an arbitrary choice, so the error aborts.","triggerScenarios":"Recording a case where two or more sanitized channel candidates both pass semantic-observation matching and strict replay — e.g. a request that succeeds identically on both short and long HID++ channels.","commonSituations":"Recording feature queries that are channel-agnostic so both channel variants replay identically; overly permissive sanitization making candidates indistinguishable; targeting a device where the operation has no channel-specific behavior.","solutions":["Constrain the target with a more specific --channel so only one candidate is considered","Choose an operation/observation that discriminates channels (channel-specific semantics)","If ambiguity is legitimate for this case, adjust the fixture plan/sanitization to pin the expected channel explicitly"],"exampleFix":"// before (ambiguous)\nopenlogi fixture record-case --name battery-query   # matches both channels\n// after: pin the channel\nopenlogi fixture record-case --name battery-query --channel short-hidpp","handlingStrategy":"validation","validationCode":"// pin the channel explicitly to avoid ambiguous candidate matching\nlet args = RecordCaseArgs { channel: \"short-hidpp\".into(), ..default };\nassert!(!args.channel.is_empty());","typeGuard":null,"tryCatchPattern":"if err.to_string().contains(\"resolution is ambiguous\") {\n    eprintln!(\"multiple channels match; pass a specific --channel to disambiguate\");\n}","preventionTips":["Always specify an explicit --channel for channel-agnostic operations","Design fixture cases around channel-specific semantics when possible","Pin expected channel in the fixture plan"],"tags":["fixture","replay","ambiguity","validation"],"backgroundTag":"unexpected-response-shape","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"}