{"record":{"id":"31569a8dd4ff6dac","repo":"Zackriya-Solutions/meetily","slug":"device-type-input-output-not-specified-in-the-na","errorCode":null,"errorMessage":"Device type (input/output) not specified in the name","messagePattern":"Device type \\(input/output\\) not specified in the name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"frontend/src-tauri/src/audio/devices/configuration.rs","lineNumber":82,"sourceCode":"    }\n\n    pub fn from_name(name: &str) -> Result<Self> {\n        if name.trim().is_empty() {\n            return Err(anyhow!(\"Device name cannot be empty\"));\n        }\n\n        let (name, device_type) = if name.to_lowercase().ends_with(\"(input)\") {\n            (\n                name.trim_end_matches(\"(input)\").trim().to_string(),\n                DeviceType::Input,\n            )\n        } else if name.to_lowercase().ends_with(\"(output)\") {\n            (\n                name.trim_end_matches(\"(output)\").trim().to_string(),\n                DeviceType::Output,\n            )\n        } else {\n            return Err(anyhow!(\n                \"Device type (input/output) not specified in the name\"\n            ));\n        };\n\n        Ok(AudioDevice::new(name, device_type))\n    }\n}\n\nimpl fmt::Display for AudioDevice {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(\n            f,\n            \"{} ({})\",\n            self.name,\n            match self.device_type {\n                DeviceType::Input => \"input\",\n                DeviceType::Output => \"output\",\n            }","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/devices/configuration.rs#L64-L100","documentation":"Thrown by AudioDevice::from_name (configuration.rs:82) when the name does not end with the literal '(input)' or '(output)' suffix (case-insensitive). The parser encodes device direction in the display name itself - the same physical device appears once per suffix in device lists - so a bare name is ambiguous and rejected rather than guessed. It is a contract error between the device-listing API and the device-lookup API.","triggerScenarios":"Calling AudioDevice::from_name(\"MacBook Pro Microphone\") without a suffix; double-parsing a stored name (from_name strips the suffix, so from_name(from_name(x).name) loses it the second time); UI code that displays the pretty name (suffix removed by Display/serde) and feeds that displayed value back into from_name; suffix spacing variants like '( input )'.","commonSituations":"Round-tripping an AudioDevice through its Display representation or a serde JSON that serializes the trimmed name; a frontend dropdown storing device.name (suffix-stripped) instead of the full labeled string; version drift where an older build stored names without suffixes.","solutions":["If the direction is known, construct directly: AudioDevice::new(name, DeviceType::Input) - no suffix parsing involved.","Store and pass the full labeled string 'Device (input)'/'Device (output)' exactly as returned by list_audio_devices.","When re-parsing a stored AudioDevice name, re-append the suffix from the known device_type instead of calling from_name.","Normalize before parsing: re-append the suffix with format! so the name carries the expected '(input)'/'(output)' marker."],"exampleFix":"// before: Display round-trip loses the suffix\nlet dev = AudioDevice::from_name(\"MacBook Pro Microphone\")?; // Err\n\n// after: construct with an explicit type when direction is known\nlet dev = AudioDevice::new(\"MacBook Pro Microphone\".to_string(), DeviceType::Input);","handlingStrategy":"validation","validationCode":"// Rust: ensure the suffixed form before parsing\nfn ensure_suffixed(name: &str, dt: DeviceType) -> String {\n    if name.to_lowercase().ends_with(\"(input)\") || name.to_lowercase().ends_with(\"(output)\") {\n        name.to_string()\n    } else {\n        let dir = match dt { DeviceType::Input => \"input\", DeviceType::Output => \"output\" };\n        format!(\"{} ({})\", name, dir)\n    }\n}\nlet dev = AudioDevice::from_name(&ensure_suffixed(raw, DeviceType::Input))?;","typeGuard":"fn carries_device_type_suffix(name: &str) -> bool {\n    let n = name.to_lowercase();\n    n.ends_with(\"(input)\") || n.ends_with(\"(output)\")\n}","tryCatchPattern":null,"preventionTips":["Store the full 'Name (input)'/'Name (output)' string from list_audio_devices; never the Display-trimmed name.","When the direction is already known at the call site, prefer AudioDevice::new(name, device_type) over from_name.","Do not round-trip AudioDevice through Display or a trimmed serde field."],"tags":["audio","validation","device-name","parse-error"],"backgroundTag":"invalid-device-identifier","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}