{"record":{"id":"f2edd1511a86d6a1","repo":"Aider-AI/aider","slug":"device-device-name-not-found-available-input","errorCode":null,"errorMessage":"Device '{device_name}' not found. Available input devices: {available_inputs}","messagePattern":"Device '(.+?)' not found\\. Available input devices: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"aider/voice.py","lineNumber":60,"sourceCode":"            raise SoundDeviceError\n        try:\n            print(\"Initializing sound device...\")\n            import sounddevice as sd\n\n            self.sd = sd\n\n            devices = sd.query_devices()\n\n            if device_name:\n                # Find the device with matching name\n                device_id = None\n                for i, device in enumerate(devices):\n                    if device_name in device[\"name\"]:\n                        device_id = i\n                        break\n                if device_id is None:\n                    available_inputs = [d[\"name\"] for d in devices if d[\"max_input_channels\"] > 0]\n                    raise ValueError(\n                        f\"Device '{device_name}' not found. Available input devices:\"\n                        f\" {available_inputs}\"\n                    )\n\n                print(f\"Using input device: {device_name} (ID: {device_id})\")\n\n                self.device_id = device_id\n            else:\n                self.device_id = None\n\n        except (OSError, ModuleNotFoundError):\n            raise SoundDeviceError\n        if audio_format not in [\"wav\", \"mp3\", \"webm\"]:\n            raise ValueError(f\"Unsupported audio format: {audio_format}\")\n        self.audio_format = audio_format\n\n    def callback(self, indata, frames, time, status):\n        \"\"\"This is called (from a separate thread) for each audio block.\"\"\"","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/Aider-AI/aider/blob/5dc9490bb35f9729ef2c95d00a19ccd30c26339c/aider/voice.py#L42-L78","documentation":"Voice.__init__ in aider/voice.py enumerates sounddevice devices via sd.query_devices() and, when a device_name was supplied, does substring matching against each device's name. If no device name contains the requested substring, it raises ValueError listing all devices with max_input_channels > 0. Two caveats from the source: matching is case-sensitive substring containment, and the whole block is wrapped in except (OSError, ModuleNotFoundError) -> SoundDeviceError, so backend failures masquerade as a different error.","triggerScenarios":"Constructing Voice(device_name=\"...\") where the substring appears in no installed device name — typo, wrong casing ('MacBook' vs 'MacBook Pro' casing differences), device unplugged/disabled, or name from a different machine. Available input device names are printed in the error, so you can diff requested vs actual.","commonSituations":"Hardcoding an input device name from one machine onto another (headset disconnected, USB mic moved); Linux where PulseAudio/PipeWire device names differ from the GUI labels; casing mismatches since 'in device[\"name\"]' is exact-case substring matching.","solutions":["Copy an exact substring from the 'Available input devices' list in the error message, keeping the casing.","Verify the device is connected and enabled at OS level (unplug/replug, check system sound settings) and retry.","Omit device_name entirely (self.device_id = None) to use the system default input.","List devices first to pick the name programmatically: python -c \"import sounddevice as sd; [print(i, d['name']) for i, d in enumerate(sd.query_devices())]\"."],"exampleFix":"# before\nvoice = Voice(device_name=\"Yeti\")   # ValueError if actual name is 'Blue Yeti 2'\n\n# after\nimport sounddevice as sd\nnames = [d[\"name\"] for d in sd.query_devices() if d[\"max_input_channels\"] > 0]\npick = next((n for n in names if \"yeti\" in n.lower()), None)\nvoice = Voice(device_name=pick)  # None -> system default","handlingStrategy":"validation","validationCode":"import sounddevice as sd\n\ndef resolve_device(name=None):\n    try:\n        devices = sd.query_devices()\n    except (OSError, ModuleNotFoundError):\n        return None  # no audio backend at all\n    inputs = [d[\"name\"] for d in devices if d[\"max_input_channels\"] > 0]\n    if name:\n        for n in inputs:\n            if name in n:  # same substring rule as Voice.__init__\n                return n\n    return inputs[0] if inputs else None  # fall back to default","typeGuard":null,"tryCatchPattern":"try:\n    voice = Voice(device_name=name)\nexcept ValueError as e:\n    if \"not found. Available input devices\" in str(e):\n        voice = Voice()  # retry with system default\n    else:\n        raise","preventionTips":["Enumerate devices and substring-match exactly like the source does (case-sensitive 'name in device[\"name\"]') before constructing Voice.","Prefer passing None (default device) unless you specifically need a non-default mic.","Device names differ across machines — never hardcode them in shared scripts."],"tags":["audio","voice","device-selection","sounddevice","aider"],"backgroundTag":null,"analyzedSha":"5dc9490bb35f9729ef2c95d00a19ccd30c26339c","analyzedAt":"2026-08-15T05:40:10.498Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}