Expected Behavior
When the number of connected clients exceeds MaxConnectedClients, edgeHub should reject new connection, as described here:
https://learn.microsoft.com/en-us/azure/iot-edge/iot-edge-limits-and-restrictions
Current Behavior
edgeHub accepts new connections even when the number of connected clients exceeds MaxConnectedClients, when clients were connected successfully before, because their entries stay in the dictionary and check for MaxConnectedClients is skipped.
Steps to Reproduce
Provide a detailed set of steps to reproduce the bug.
- Prepare a parent Edge device, with 2 module connections to the edgeHub
- Preare a child Edge device A, B, C, which will make 7 client connections to the upstream each
- Start Parent Edge device with MaxConnectedClients environment variable set to 9
- [On Parent] Confirm that the environment variable MaxConnectedClients is set to "9" using the docker inspect edgeHub command
- [On Parent] Confirm that the number of client connections is 2 from the edgehub_connected_clients metric on the parent
- Start downstream Edge device (A)
- [On Parent] Confirm that the number of client connections is 9 (= 2 + 7) from the edgehub_connected_clients metric
- Stop downstream Edge device (A)
- [On Parent] Confirm that the number of client connections is 2 from the edgehub_connected_clients metric
- Start downstream Edge device (B)
- [On Parent] Confirm that the number of client connections is 9 (= 2 + 7) from the edgehub_connected_clients metric
- Started downstream Edge device (A)
- [On Parent] Confirm that the number of client connections is 16 (= 2 + 7 + 7) from the edgehub_connected_clients metric
- Since MaxConnectedClients is set to "9", an error is expected at this point and the value should remain at "9" instead of "16"
- Start downstream Edge device (C)
- [On Parent] Confirm that an error occurred in the edgeHub module
Microsoft.Azure.Devices.Edge.Hub.Core.EdgeHubConnectionException: Edge hub already has maximum allowed clients (9) connected.
- Based on this error, it is determined that the MaxConnectedClients limit is being enforced
- However, the behavior suggests that the evaluation logic may differ between clients that were previously connected to edgeHub and newly connecting clients
Context (Environment)
edgeHub
https://github.com/Azure/iotedge/blob/main/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs#L398
ConnectedDevice CreateNewConnectedDevice(IIdentity identity)
{
lock (this.deviceConnLock)
{
if (this.devices.Values.Count(d => d.DeviceConnection.Filter(d1 => d1.IsActive).HasValue) >= this.maxClients)
{
throw new EdgeHubConnectionException($"Edge hub already has maximum allowed clients ({this.maxClients - 1}) connected.");
}
return new ConnectedDevice(identity);
}
}
Output of iotedge check
(The issue does not depend on the environment)
Device Information
- Host OS [e.g. Ubuntu 22.04, Windows Server IoT 2019]: Not limited to the specific OS because this is the code defect of edgeHub container
- Architecture [e.g. amd64, arm32, arm64]: Not limited to the specific architecture because this is the code defect of edgeHub container
- Container OS [e.g. Linux containers, Windows containers]: Not limited to the specific Container OS because this is the code defect of edgeHub container
Runtime Versions
- aziot-edged [run
iotedge version]: 1.5.21
- Edge Agent [image tag (e.g. 1.0.0)]: 1.5.15 or later
- Edge Hub [image tag (e.g. 1.0.0)]: 1.5.15 or later
- Docker/Moby [run
docker version]: 23.0.6+azure-2
Note: when using Windows containers on Windows, run docker -H npipe:////./pipe/iotedge_moby_engine version instead
Logs
edge-hub logs
<7> 2026-05-28 02:23:04.511 +00:00 [DBG] [Microsoft.Azure.Devices.Edge.Hub.Core.IDeviceScopeIdentitiesCache] - Getting service identity for <Device ID of Edge C>/$edgeHub
<6> 2026-05-28 02:23:04.512 +00:00 [INF] [Microsoft.Azure.Devices.Edge.Hub.Core.DeviceScopeAuthenticator] - Client <Device ID of Edge C>/$edgeHub in device scope authenticated locally.
<7> 2026-05-28 02:23:04.512 +00:00 [DBG] [Microsoft.Azure.Devices.Edge.Hub.Core.Authenticator] - Client <Device ID of Edge C>/$edgeHub authentication successful
<3> 2026-05-28 02:23:04.513 +00:00 [ERR] [Microsoft.Azure.Devices.Edge.Hub.Core.Device.DeviceMessageHandler] - Error binding device proxy for device <Device ID of Edge C>/<Module ID>
Microsoft.Azure.Devices.Edge.Hub.Core.EdgeHubConnectionException: Edge hub already has maximum allowed clients (9) connected.
at Microsoft.Azure.Devices.Edge.Hub.Core.ConnectionManager.CreateNewConnectedDevice(IIdentity identity) in /mnt/vss/_work/1/s/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs:line 400
at Microsoft.Azure.Devices.Edge.Hub.Core.ConnectionManager.<>c__DisplayClass42_0.<GetOrCreateConnectedDevice>b__0(String id) in /mnt/vss/_work/1/s/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs:line 381
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Azure.Devices.Edge.Hub.Core.ConnectionManager.GetOrCreateConnectedDevice(IIdentity identity) in /mnt/vss/_work/1/s/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs:line 379
at Microsoft.Azure.Devices.Edge.Hub.Core.ConnectionManager.AddDeviceConnection(IIdentity identity, IDeviceProxy deviceProxy) in /mnt/vss/_work/1/s/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs:line 68
at Microsoft.Azure.Devices.Edge.Hub.Core.Device.DeviceMessageHandler.BindDeviceProxyAsync(IDeviceProxy deviceProxy, Option`1 initWhenBound) in /mnt/vss/_work/1/s/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/device/DeviceMessageHandler.cs:line 268
Additional Information
Please provide any additional information that may be helpful in understanding the issue.
From the source https://github.com/Azure/iotedge/blob/main/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs, the check for MaxConnectedClients only runs inside a factory method that creates new entries in an internal dictionary. When a device disconnects, its entry stays in the dictionary (marked inactive but not removed). When that device reconnects, the dictionary returns the existing entry and skips the factory entirely, so the limit check never fires. That's why device A reconnecting pushed the count to 16 with no error, but device C (a new identity) was correctly rejected.
This affects any scenario where devices disconnect and reconnect, which is normal in steady-state IoT deployments. The limit works on first connection but silently stops being enforced after restarts.
Potential fix: The check for maxClients needs to be moved into AddDeviceConnection rather than only in the CreateNewConnectedDevice.
Expected Behavior
When the number of connected clients exceeds MaxConnectedClients, edgeHub should reject new connection, as described here:
https://learn.microsoft.com/en-us/azure/iot-edge/iot-edge-limits-and-restrictions
Current Behavior
edgeHub accepts new connections even when the number of connected clients exceeds MaxConnectedClients, when clients were connected successfully before, because their entries stay in the dictionary and check for MaxConnectedClients is skipped.
Steps to Reproduce
Provide a detailed set of steps to reproduce the bug.
Microsoft.Azure.Devices.Edge.Hub.Core.EdgeHubConnectionException: Edge hub already has maximum allowed clients (9) connected.
Context (Environment)
edgeHub
https://github.com/Azure/iotedge/blob/main/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs#L398
Output of
iotedge check(The issue does not depend on the environment)
Device Information
Runtime Versions
iotedge version]: 1.5.21docker version]: 23.0.6+azure-2Note: when using Windows containers on Windows, run
docker -H npipe:////./pipe/iotedge_moby_engine versioninsteadLogs
edge-hub logs
Additional Information
Please provide any additional information that may be helpful in understanding the issue.
From the source https://github.com/Azure/iotedge/blob/main/edge-hub/core/src/Microsoft.Azure.Devices.Edge.Hub.Core/ConnectionManager.cs, the check for MaxConnectedClients only runs inside a factory method that creates new entries in an internal dictionary. When a device disconnects, its entry stays in the dictionary (marked inactive but not removed). When that device reconnects, the dictionary returns the existing entry and skips the factory entirely, so the limit check never fires. That's why device A reconnecting pushed the count to 16 with no error, but device C (a new identity) was correctly rejected.
This affects any scenario where devices disconnect and reconnect, which is normal in steady-state IoT deployments. The limit works on first connection but silently stops being enforced after restarts.
Potential fix: The check for maxClients needs to be moved into AddDeviceConnection rather than only in the CreateNewConnectedDevice.