MQTT Client-ID Collisions: Diagnose Session Takeover in a Device Fleet
If two MQTT clients repeatedly disconnect just after the other connects, compare their actual Client Identifiers before changing Wi-Fi or keepalive settings. Two accepted connections using the same identifier can replace one another at the server. The repair is an intentional identity and connection-ownership contract, supported by a provisioning uniqueness check.
This guide uses the OASIS MQTT Version 5.0 Standard, 7 March 2019. Broker authorization policy, clustering and client-library reconnect behavior remain implementation-specific. The two-client experiment below is a proposed isolated-lab procedure; no broker connection or fleet measurement was executed for this article.
Separate the identifier from the physical device
The Client Identifier associates the connection with MQTT session state. It is not automatically a board serial number, a certificate identity or the name printed on a configuration screen. A device can have multiple software clients, and each concurrently connected client needs a deliberately assigned identity in the relevant server scope.
Build an identity ledger with device inventory ID, firmware build, process or service role, effective ClientID, broker endpoint and connection generation. Include where the identifier came from: provisioning record, environment variable, SDK default, generated file or cloned image. Record exact effective values rather than assuming a display label matches the CONNECT packet.
Keep credentials out of this ledger. If an authentication principal is needed to distinguish clients, record an approved nonsecret identifier. ClientID uniqueness does not replace authentication or authorization; it solves a separate ownership problem.

Reconstruct the accepted-connection sequence
MQTT 5.0 section 3.1.4 specifies takeover processing after CONNECT validation succeeds: an existing connection with the same ClientID is closed, with Session taken over reason 0x8E described for the disconnect. An invalid or unauthorized connection attempt must not simply be assumed to have reached that accepted-takeover step.
Correlate the new connection’s successful acceptance with the old connection’s closure. Capture the reason code when available, but do not infer absence of takeover merely because a client did not receive a useful final packet. Network loss and incomplete client logging can hide that evidence; server-side connection records are important.
The standard then processes Clean Start. Changing Clean Start does not permit two accepted connections with the same identifier to coexist. It changes session-state handling, so a diagnostic experiment that toggles it can also change subscriptions or other retained session behavior and confuse the investigation.
Run a controlled two-client test
- Create an isolated lab namespace and two test clients with no actuator command path and no Will messages. Record broker and client-library versions.
- Disable automatic reconnect initially so the first replacement produces a readable sequence.
- Connect client A using a test identifier and confirm successful acceptance.
- Connect client B using the same identifier and permitted credentials. Observe B’s acceptance and A’s closure, including reason 0x8E where delivered and logged.
- Reconnect A deliberately with the same identifier and observe the reverse ownership change.
- Assign distinct identifiers to A and B, reconnect both and verify that this collision-driven replacement stops.
Do not run this test with a production identifier: it is designed to displace an existing connection. Do not use a real device’s credentials merely to make the lab look realistic. The useful control is one changed variable, identifier uniqueness, while the endpoint and ordinary connection policy remain comparable.
Distinguish collision evidence from similar symptoms
| Observation | Next interpretation check |
|---|---|
| Accepted B immediately precedes A’s takeover reason | Compare exact ClientID and provisioning source |
| A disconnects with no competing accepted connection | Investigate transport, keepalive or another server policy |
| B is rejected before session acceptance | Inspect authentication, authorization and CONNECT validity |
| Two distinct configured labels still collide | Inspect the effective identifier actually sent by each library |
Use connection generations to avoid confusing one client’s reconnect with a second physical device. Likewise, multiple interfaces on one device can accidentally launch duplicate client instances. A uniqueness check over hardware inventory alone will miss two processes using the same device-level identifier.
Audit provisioning and clone paths
Search factory images, test scripts, container settings and fallback configuration for fixed identifiers. Check what happens when provisioning data is absent or unreadable: a convenient default can turn a rare configuration failure into a fleet-wide collision. Make the failure explicit rather than silently connecting under a shared placeholder.
For a hypothetical fleet image, suppose the normal path reads a unique provisioned ID, but the service fallback uses “gateway.” Two newly replaced storage devices then alternate ownership of that identifier. The diagnostic ledger should identify the fallback source and the exact condition that selected it. A randomized retry delay might make the pattern less frequent, but it does not remove the shared identity.
Define which identity survives firmware upgrades, factory reset, service replacement and intentional session migration. Do not generate a new identifier on every retry simply to suppress takeover logs without considering the required session continuity. Concurrent roles can have distinct identities while a single role retains its intended identity across ordinary reconnects.
Qualify the repair at fleet scale
Before connecting a rollout, check the intended concurrent ClientIDs for duplicates within the relevant server deployment. Then test cloned-image startup, missing provisioning, duplicate service launch and restart of one client while another remains connected. Keep the experiment’s identifiers and expected owners explicit.
Acceptance requires that each intended concurrent client has a unique effective identifier, each deliberate takeover is attributable to an approved ownership transition, and unexpected replacement produces actionable diagnostics. Archive the identity-generation rule and regression cases with the release. A quiet reconnect log is useful only when the underlying ownership ledger also agrees.