{"record":{"id":"114fb37e6469fcbe","repo":"home-assistant/core","slug":"config-entry-config-entry-id-not-found","errorCode":null,"errorMessage":"Config entry {config_entry_id} not found","messagePattern":"Config entry (.+?) not found","errorType":"exception","errorClass":"InvalidConfigEntryID","httpStatus":null,"severity":"error","filePath":"homeassistant/components/bluetooth/util.py","lineNumber":131,"sourceCode":"            ):\n                connectable_loaded_history[address] = service_info\n\n    return all_loaded_history, connectable_loaded_history\n\n\n@callback\ndef adapter_title(adapter: str, details: AdapterDetails) -> str:\n    \"\"\"Return the adapter title.\"\"\"\n    unique_name = adapter_unique_name(adapter, details[ADAPTER_ADDRESS])\n    model = details.get(ADAPTER_PRODUCT, \"Unknown\")\n    manufacturer = details[ADAPTER_MANUFACTURER] or \"Unknown\"\n    return f\"{manufacturer} {model} ({unique_name})\"\n\n\ndef config_entry_id_to_source(hass: HomeAssistant, config_entry_id: str) -> str:\n    \"\"\"Convert a config entry id to a source.\"\"\"\n    if not (entry := hass.config_entries.async_get_entry(config_entry_id)):\n        raise InvalidConfigEntryID(f\"Config entry {config_entry_id} not found\")\n    source = entry.unique_id\n    assert source is not None\n    if not get_manager().async_scanner_by_source(source):\n        raise InvalidSource(f\"Source {source} not found\")\n    return source\n","sourceCodeStart":113,"sourceCodeEnd":137,"githubUrl":"https://github.com/home-assistant/core/blob/58a3fdb3ea0538617f0a07efcfba6294de64fd59/homeassistant/components/bluetooth/util.py#L113-L137","documentation":"InvalidConfigEntryID raised by config_entry_id_to_source: hass.config_entries.async_get_entry(config_entry_id) returned nothing, so the passed id does not correspond to any existing config entry (deleted, never existed, or typo'd). The function exists to turn a Bluetooth config entry id into a scanner source address.","triggerScenarios":"Calling config_entry_id_to_source (directly or via a websocket/API that accepts a config_entry_id) with an id from a stale UI session after the entry was removed, a truncated id, or a random string.","commonSituations":"Frontend dialog holding an entry id across a reload/delete; scripts or blueprints referencing an entry that was re-created with a new id; copy-paste of an id with missing characters.","solutions":["Re-fetch the current config entry id (Settings > Devices & Services, or config_entries API) and pass that","If the entry was deleted intentionally, remove the automation/script/UI element that still stores the old id","Catch InvalidConfigEntryID and re-enumerate entries instead of retrying the same id"],"exampleFix":"# before\nsource = config_entry_id_to_source(hass, stale_entry_id)\n\n# after\nentry = hass.config_entries.async_entries(bluetooth.__dict__['DOMAIN'])[0]\nsource = config_entry_id_to_source(hass, entry.entry_id)","handlingStrategy":"validation","validationCode":"def config_entry_exists(hass, config_entry_id: str) -> bool:\n    return hass.config_entries.async_get_entry(config_entry_id) is not None","typeGuard":null,"tryCatchPattern":"from homeassistant.components.bluetooth.util import InvalidConfigEntryID\ntry:\n    source = config_entry_id_to_source(hass, entry_id)\nexcept InvalidConfigEntryID:\n    entry_id = hass.config_entries.async_entries(\"bluetooth\")[0].entry_id  # re-resolve\n    source = config_entry_id_to_source(hass, entry_id)","preventionTips":["Resolve entry ids at call time, never cache them across reloads/deletes","In UIs, re-fetch the entry list when a stored id fails validation"],"tags":["bluetooth","config-entry","invalid-id"],"backgroundTag":null,"analyzedSha":"58a3fdb3ea0538617f0a07efcfba6294de64fd59","analyzedAt":"2026-08-14T20:54:38.818Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}