android icon indicating copy to clipboard operation
android copied to clipboard

Companion app synchronizes old/deleted openthread credentials

Open brodock opened this issue 6 months ago • 9 comments

Home Assistant Android app version(s): 2025.8.7-full

Android version(s): 15

Device model(s): Galaxy S24 Plus

Home Assistant version: 2025.10.0b4

Last working Home Assistant release (if known):

Description of problem, include YAML if issue is related to notifications:

Companion App Logs:

09-27 23:31:21.537 22114 22114 D ThreadManagerImpl: Thread device prefers app added dataset: ha-thread-cb0f (PAN 51983, EXTPAN     Q ?\)
09-27 23:31:21.537 22114 22114 D ThreadManagerImpl: Thread: device prefers dataset from app

Screenshot or video of problem:

Image

Additional information:

I've had to reset my Thread / OpenThread Border Router recently and since then I can't get it to work on the Android app. I had to resort to an iPad I hadn't synced Thread before, to be able to re-pair the devices.

It seems the credentials are cached on the Android app somehow and I can't update it no matter what I try. I've done everything from clearing up cache for the HA companion app, to the Google Play Services, I've tried to force credentials resync (which is what is in the logs, but it seems it's syncing the old one: ha-thread-cb0f instead of the new one ha-thread-9267

brodock avatar Sep 27 '25 21:09 brodock

If you tap the ... menu for the new network, is that the preferred network for the companion apps (the option should be greyed out)?

but it seems it's syncing the old one: ha-thread-cb0f instead of the new one ha-thread-9267

The very small log snippet you posted only indicates that your device preferred the old one. The app will try to update it if set correctly, but the options for the app to do so are unfortunately quite limited...


I expect to see a log line above your snippet like (one of them, not both):

Thread: device prefers core preferred dataset
Thread: device doesn't prefer core preferred dataset

which will also answer question 1.

If the datasets are different, it should also have a log line with:

Thread update device completed:  (action)

jpelgrom avatar Sep 28 '25 06:09 jpelgrom

Yes, it's grayed out.

I've read previous issues where it seems people were having issues with third party border routers (like from Google/Apple), and I understand HA may not have access to those credentials. This seems to be different, because the credentials were originally added by HA itself.

What I believe is happening here is that HA is not aware of ha-thread-cb0f anymore (as it was deleted), but it may still have access to modify it because it's tied to HA application.

I've run the sync again and these are the only ThreadManagerImpl related logs:

09-28 19:41:30.378 23584 23584 D ThreadManagerImpl: Thread device prefers app added dataset: ha-thread-cb0f (PAN 51983, EXTPAN     Q ?\)
09-28 19:41:30.379 23584 23584 D ThreadManagerImpl: Thread: device prefers dataset from app
09-28 19:41:30.462 23584 23584 D ThreadManagerImpl: Thread update device completed: deleted 0 datasets, updated 1

brodock avatar Sep 28 '25 17:09 brodock

I believe what I said before is what is going on here.

See: https://github.com/home-assistant/android/blob/5dcfe6cd8ae30d22d0e181ee803f685efd234c06/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt#L145-L172

We iterate over the known credentials from server, but because ha-thread-cb0f was removed, we never iterate over it to unflag it as preferred nor to delete it.

What we may need to do instead is look at all credentials and check which ones we have access, and them compare with what we have from the server, so we can identify what to delete.

See: https://developers.home.google.com/thread#credentials_ownership_and_maintenance

brodock avatar Sep 29 '25 05:09 brodock

@brodock can I work on this

ujjol1234 avatar Sep 29 '25 13:09 ujjol1234

We iterate over the known credentials from server, but because ha-thread-cb0f was removed, we never iterate over it to unflag it as preferred nor to delete it.

I understand what you're thinking, but think your assumption is that serverManager.integrationRepository(it.id).getThreadBorderAgentIds() fetches data from the server. That is incorrect: it is the list of Thread networks previously added by the app for that server. So, this function should return the ID for the old network the first time. Then, because it is no longer preferred, it is deleted in line 151.

That brings us to the question why the device still seems to prefer it, it seems the delete operation failed or was ignored. It might be possible to improve that.

What we may need to do instead is look at all credentials and check which ones we have access, and them compare with what we have from the server, so we can identify what to delete.

Unfortunately the API doesn't allow that. The app can only get the preferred credential (from whatever app) and credentials it added itself.

  • The app will only ever add one credential (because there is no way for the user to choose a preferred network, whichever one is first is preferred on the device).
  • We already get the preferred credential and check if that's from HA or another app:
    • If from another app, it is imported to HA
    • If from HA or none, it is added/updated/removed to match whatever you set as preferred on your server
  • When retrieving the device's preferred credential or app-added credentials, we get Thread network credentials. To delete credentials, you need to remove it by Thread border agent. So the API on the device doesn't give us the ID we need to delete a credential. That means the app needs to keep track of which border agents it added to be able to delete it, which is what it is doing in the function mentioned at the start of this message.

jpelgrom avatar Sep 30 '25 20:09 jpelgrom

your assumption is that serverManager.integrationRepository(it.id).getThreadBorderAgentIds() fetches data from the server. That is incorrect: it is the list of Thread networks previously added by the app for that server.

thank you for clarifying that.

from your explanation I shouldn't be having issues here, but for whatever reason I still get a previously deleted credential stuck.

A bit of the frustration during this process is the lack of any information from frontend. Even in the forced resync, I only get a generic confirmation message.

I'm planning on putting some time to try to debug this myself (android is not what I program daily so this will be a bit of a challenge).

If anything I believe we could improve the success message by including a more detailed status at the end along with the "success" message, something that includes:

  • List known credentials
  • Show which was added (can be a ➕ icon in the displayed list item)
  • Show which was removed (can be a ➖ or 🗑️ icon in the displayed list item)
  • Show which one failed (if any) (can be a ⚠️ or ⛔️ icon in the displayed list item)
  • Show which one was set as preferred (we already have a symbol for that so we can reuse that)

That alone would remove a lot of guess-work and make it easy to figure out when something doesn't work properly.

brodock avatar Oct 04 '25 00:10 brodock

I am experiencing an issue that appears to be a hang during the final stage of Thread network commissioning. The network that is being checked doesn't exist anymore, which might have something to do with this issue.

Problem started occurring after i reinstalled the OpenThread Border Router Add-on and Thread service.

JelleBuning avatar Nov 07 '25 07:11 JelleBuning

I am experiencing an issue that appears to be a hang during the final stage of Thread network commissioning. The network that is being checked doesn't exist anymore, which might have something to do with this issue.

Problem started occurring after i reinstalled the OpenThread Border Router Add-on and Thread service.

I deleted a previous Thread network while trying to debug an issue with a Matter device and now the app is permanently stuck trying to sync an already deleted network instead of the newly created one as well.

RavenXce avatar Nov 14 '25 15:11 RavenXce

Clearing cache & data from Google Play services solved this issue for me.

JelleBuning avatar Nov 25 '25 14:11 JelleBuning

Hi. Today I noticed that the OpenThread Border Router Add-on was shut down after I deleted the only Thread device I have from Home Assistant. After factory reset the device I tried to connect to Home Assistant and that's when I notice that the OpenThread Border Router Add-on was shut down.

After deleting all the Thread configuration, shutting down the system and starting all over again, I was able to create a new Thread network. But on my Android device (Pixel 9 Pro) when I synced the new Thread network always tries to connect the device to the old network, something similar to @JelleBuning problem. I have tried several times to sync the network into my Android via the Troubleshooting menu.

I was able to add the device to my Home Assistant Thread network giving admin permission to my girlfriend and using her android (pixel 6) to configure the device. I didn't though on deleting the cache of Google Play services.

Fonsos avatar Dec 18 '25 18:12 Fonsos