home-assistant / home-assistant/supervisor

HA Supervisor periodically reports host_internet: false and blocks addon/supervisor updates, but the host has full internet connectivity. Only fix is ha supervisor restart.

Open
#6,748 4 comments 2 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
2.2k
Forks
807
Avg merge
1d 6h
Merged PRs (30d)
55

Description

### Describe the issue you are experiencing

## Symptom

HA Supervisor periodically reports host_internet: false and blocks addon/supervisor
updates ('AddonManager.update' blocked from execution, no host internet connection).
The host has full internet connectivity throughout — integrations keep working.
Only fix is ha supervisor restart.

Observed in Supervisor 12.6.1 on HA OS (Alpine 3.23.3), Proxmox VM, macmini1.

# update May 2,2026

Additional symptom: AppArmor update abort
The dead D-Bus socket also manifests as a hard update block with a misleading AppArmor error:

ERROR [supervisor.host.apparmor] Can't load profile hassio-supervisor: [Errno 9] Bad file descriptor
ERROR [supervisor.supervisor] Can't update AppArmor profile!
CRITICAL [supervisor.supervisor] Abort update because of an issue with AppArmor: Can't update AppArmor profile!

The [Errno 9] Bad file descriptor is the same dead D-Bus socket — not an actual AppArmor problem. The supervisor fetches the new profile successfully from , then tries to load it via the AppArmor D-Bus interface, hits the dead fd, and aborts the entire update.
In the logs I captured, the connectivity D-Bus error appeared at 10:47 and the AppArmor abort happened at 11:22 — the socket had been dead ~35 minutes before an update was attempted.
Same fix: ha supervisor restart resolves both symptoms.
Worth calling out because “Can’t update AppArmor profile” sends users down an AppArmor/kernel troubleshooting path when the real issue is the D-Bus reconnection bug.

## Root Cause

The Supervisor conflates a broken D-Bus connection with an actual internet outage.

Full failure chain:

1. Something causes the dbus_fast MessageBus socket to go dead (EOF — likely a
transient NM event: DHCP renew, Docker network churn, VM NIC reset).

2. NetworkManager fires a burst of properties_changed D-Bus signals at the same time.

3. DBus.sync_property_changes callback fires (supervisor/utils/dbus.py:261).
It calls update(changed) → NetworkInterface.update() (dbus/network/interface.py:167)
→ self.connection.connect(self.connected_dbus.bus) → DBus.connect() → init_proxy()
→ introspect().

4. introspect() retries 3× catching EOFError (bus is dead), then raises:
DBusFatalError: Could not get introspection data after 3 attempts

5. sync_property_change has no try/except, so the exception becomes an unhandled
asyncio task — logged as "Task exception was never retrieved". The burst means
this fires 30+ times simultaneously (Task-80999851 through ~880).

6. All subsequent D-Bus calls on the dead bus fail with [Errno 9] Bad file descriptor.

7. check_connectivity() in supervisor/host/network.py catches DBusError and sets
self.connectivity = False. This runs on every periodic check, always fails, always
returns False. The Supervisor never recovers.

The bug is that step 7 equates a D-Bus connection error with "no internet":
```
# supervisor/host/network.py ~line 152
except DBusError as err:
_LOGGER.warning("Can't update connectivity information: %s", err)
self.connectivity = False # ← WRONG: this is a D-Bus error, not an internet outage
```

## Proposed Fix (two files)

### Fix 1 — supervisor/utils/dbus.py around line 279

Catch DBusFatalError in sync_property_change so it doesn't leak as an unhandled
task exception. The periodic refresh will pick up any missed property changes.

```
async def sync_property_change(
prop_interface: str, changed: dict[str, Any], invalidated: list[str]
) -> None:
"""Sync property changes to cache."""
if interface != prop_interface:
return

_LOGGER.debug(
"Property change for %s-%s: %s changed & %s invalidated",
self.bus_name,
self.object_path,
list(changed.keys()),
invalidated,
)

try:
if invalidated:
await update()
else:
await update(changed)
except DBusFatalError as err:
_LOGGER.warning(
"D-Bus property change sync failed for %s-%s: %s",
self.bus_name,
self.object_path,
err,
)
```

### Fix 2 — supervisor/host/network.py around line 152 (the important one)

Use None (unknown) instead of False (definitely no internet) when the failure
is a D-Bus connection error, not an NM connectivity report:

```
except DBusError as err:
_LOGGER.warning("Can't update connectivity information: %s", err)
# A D-Bus error means we *can't check* connectivity — not that it's gone.
# Setting False permanently blocks addon updates on a false-negative.
# None (unknown) lets the Supervisor retry without blocking operations.
self.connectivity = None
```

None is already used in this codebase to mean "connectivity checking disabled/unknown"
(see the connectivity_enabled branch above this block). Downstream job checks treat
None differently from False — they don't block on unknown state.

### What type of installation are you running?

Home Assistant OS

### Which operating system are you running on?

Debian

### Steps to reproduce the issue

1. Have a blip on the hosts network
2. Host_internet goes to false
3. Never recovers. A reboot of the VM sometimes works, a full reboot of the host always works

### Anything in the Supervisor logs that might be useful for us?

```txt
None really relevant. The reasons behind the host_internet: false are varied.
```

### System information

## System Information

version | core-2026.4.3
-- | --
installation_type | Home Assistant OS
dev | false
hassio | true
docker | true
container_arch | amd64
user | root
virtualenv | false
python_version | 3.14.2
os_name | Linux
os_version | 6.12.77-haos
arch | x86_64
timezone | America/Edmonton
config_dir | /config

Home Assistant Community Store

GitHub API | ok
-- | --
GitHub Content | ok
GitHub Web | ok
HACS Data | ok
GitHub API Calls Remaining | 5000
Installed Version | 2.0.5
Stage | running
Available Repositories | 2936
Downloaded Repositories | 13

Home Assistant Cloud

logged_in | false
-- | --
can_reach_cert_server | ok
can_reach_cloud_auth | ok
can_reach_cloud | ok

Home Assistant Supervisor

host_os | Home Assistant OS 17.2
-- | --
update_channel | stable
supervisor_version | supervisor-2026.04.0
agent_version | 1.8.1
docker_version | 29.3.1
disk_total | 30.8 GB
disk_used | 14.8 GB
nameservers | 192.168.3.1
healthy | true
supported | true
host_connectivity | true
supervisor_connectivity | true
ntp_synchronized | true
virtualization | kvm
board | ova
supervisor_api | ok
version_api | ok
installed_addons | Samba share (12.6.1), Terminal & SSH (10.1.0), File editor (6.0.0), InfluxDB (5.0.2), Network UPS Tools (0.18.0), Get HACS (1.3.1), Matter Server (8.4.0), Mosquitto broker (7.0.1)

Dashboards

dashboards | 7
-- | --
resources | 7
views | 8
mode | storage

Network Configuration

adapters | lo (disabled), enp0s18 (enabled, default, auto), hassio (disabled), docker0 (disabled), veth9548f58 (disabled), veth681df95 (disabled), veth72c860f (disabled), veth42e2f73 (disabled), vethd111e49 (disabled), vethbebe947 (disabled), veth37566a3 (disabled), vethd77ea6b (disabled), veth5090ed1 (disabled), vethe9331db (disabled), vethe67184c (disabled), enp0s18.30 (disabled), enp0s18.40 (disabled)
-- | --
ipv4_addresses | lo (127.0.0.1/8), enp0s18 (192.168.3.139/24), hassio (172.30.32.1/23), docker0 (172.30.232.1/23), veth9548f58 (), veth681df95 (), veth72c860f (), veth42e2f73 (), vethd111e49 (), vethbebe947 (), veth37566a3 (), vethd77ea6b (), veth5090ed1 (), vethe9331db (), vethe67184c (), enp0s18.30 (), enp0s18.40 ()
ipv6_addresses | lo (::1/128), enp0s18 (fdb5:a65a:2e3b:28d3:f731:3bd6:3243:61b2/64, fe80::f83c:59ca:537c:7059/64), hassio (fe80::c024:67ff:fe48:dbd6/64), docker0 (fe80::84b8:e0ff:fe34:823/64), veth9548f58 (fe80::a098:b7ff:fe8c:d333/64), veth681df95 (fe80::e06e:eeff:fe19:317/64), veth72c860f (fe80::f0f9:faff:fe92:7030/64), veth42e2f73 (fe80::2450:38ff:fede:d9/64), vethd111e49 (fe80::4f4:5fff:fe6a:13af/64), vethbebe947 (fe80::848b:8eff:fe1c:ffd5/64), veth37566a3 (fe80::fc91:12ff:fe12:cade/64), vethd77ea6b (fe80::5c0e:a2ff:fed5:43ba/64), veth5090ed1 (fe80::749c:75ff:fe84:9a06/64), vethe9331db (fe80::208a:3dff:fedd:e635/64), vethe67184c (fe80::585b:86ff:fe95:d1a1/64), enp0s18.30 (fe80::1e7a:a84:1398:6353/64), enp0s18.40 (fe80::c64e:3aeb:a5da:281/64)
announce_addresses | 192.168.3.139, fdb5:a65a:2e3b:28d3:f731:3bd6:3243:61b2, fe80::f83c:59ca:537c:7059

Recorder

oldest_recorder_run | April 7, 2026 at 4:16 AM
-- | --
current_recorder_run | April 18, 2026 at 12:33 PM
estimated_db_size | 634.23 MiB
database_engine | sqlite
database_version | 3.49.2

### Supervisor diagnostics

[config_entry-hassio-76bb24bd37b50d14ed93037c4539f3b4.json](https://github.com/user-attachments/files/26860440/config_entry-hassio-76bb24bd37b50d14ed93037c4539f3b4.json)

### Additional information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with supervisor/utils/dbus.py around sync_property_change and supervisor/host/network.py around check_connectivity(). Trace how DBusFatalError and DBusError are handled when the D-Bus socket is dead. Done means property-sync failures no longer become unhandled tasks and a D-Bus check failure remains unknown rather than falsely setting connectivity to false, while Supervisor updates can retry.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.