Describe the bug
When using DanaKit in Continuous Bluetooth mode, repeated disconnect/reconnect cycles appear to accumulate multiple concurrent keep-alive background tasks.
After several reconnect cycles, multiple keepConnectionAlive() calls begin occurring at exactly the same timestamp.
These calls then produce repeated:
A command is already running
errors, followed by disconnect timeouts, connection loss, automatic reconnects, pump synchronization failures, and eventually failed/stuck Loop cycles.
In my case, Loop later experienced an extended period where normal closed-loop operation could not continue.
Strong pattern observed in the logs
The most interesting observation is that the number of simultaneous keepConnectionAlive() calls appears to increase after every reconnect cycle.
Observed sequence:
| Time |
Simultaneous keep-alive calls |
| 00:04:59 |
2 |
| 00:07:11 |
3 |
| 00:09:19 |
4 |
| 00:11:29 |
5 |
| 00:13:37 |
6 |
This looks like an old background keep-alive task may remain alive after reconnect, while a new task is created.
The resulting pattern is approximately:
disconnect → reconnect → +1 keep-alive task → disconnect → reconnect → +1 keep-alive task
Eventually multiple keep-alive tasks execute at the same time.
Example log
At 00:11:29, five keep-alive calls were triggered at essentially the same time:
[2026-08-13T00:11:29+0800 INFO]
ContinousBluetoothManager.keepConnectionAlive:
Sending keep alive message
[2026-08-13T00:11:29+0800 INFO]
ContinousBluetoothManager.keepConnectionAlive:
Sending keep alive message
[2026-08-13T00:11:29+0800 INFO]
ContinousBluetoothManager.keepConnectionAlive:
Sending keep alive message
[2026-08-13T00:11:29+0800 INFO]
ContinousBluetoothManager.keepConnectionAlive:
Sending keep alive message
[2026-08-13T00:11:29+0800 INFO]
ContinousBluetoothManager.keepConnectionAlive:
Sending keep alive message
Immediately afterwards:
[2026-08-13T00:11:29+0800 ERROR]
ContinousBluetoothManager.keepConnectionAlive:
Failed to keep connection alive:
A command is already running
[2026-08-13T00:11:29+0800 ERROR]
ContinousBluetoothManager.keepConnectionAlive:
Failed to keep connection alive:
A command is already running
[2026-08-13T00:11:29+0800 ERROR]
ContinousBluetoothManager.keepConnectionAlive:
Failed to keep connection alive:
A command is already running
[2026-08-13T00:11:29+0800 ERROR]
ContinousBluetoothManager.keepConnectionAlive:
Failed to keep connection alive:
A command is already running
Then the Bluetooth connection times out:
[2026-08-13T00:11:29+0800 ERROR]
BluetoothManager:
Failed to disconnect:
The connection has timed out unexpectedly.
One second later the pump reconnects:
[2026-08-13T00:11:30+0800 INFO]
BluetoothManager:
Connected to pump!
[2026-08-13T00:11:31+0800 INFO]
PeripheralManager:
Connection and encryption successful!
[2026-08-13T00:11:31+0800 INFO]
ContinousBluetoothManager.keepConnectionAlive:
Sending keep alive message
[2026-08-13T00:11:33+0800 ERROR]
ContinousBluetoothManager.keepConnectionAlive:
Failed to keep connection alive:
Timeout has been hit...
The same pattern repeats
At 00:13:37, six keep-alive calls were triggered at the same timestamp.
They were immediately followed by multiple:
A command is already running
errors, followed by:
Failed to disconnect: The connection has timed out unexpectedly.
and:
No connected device
The pump then reconnects again.
This pattern repeats continuously.
Multiple background jobs also appear in the log
At another point the log contains multiple messages like:
ContinousBluetoothManager.handleBackgroundTask:
Existed background job. Not connected anymore
ContinousBluetoothManager.handleBackgroundTask:
Existed background job. Not connected anymore
at the same timestamp.
This seems consistent with multiple background tasks existing simultaneously.
Additional command contention after reconnect
Another reconnect sequence shows several operations being started at almost exactly the same time:
Connected to pump
Connection and encryption successful
updateInitialState()
keepConnectionAlive()
syncPump()
updateInitialState()
Immediately afterwards the following operations fail:
updateInitialState:
A command is already running
syncUserOptions:
A command is already running
syncHistory:
A command is already running
fetchPumpTime:
A command is already running
This suggests that the keep-alive/background tasks may not only compete with each other, but also with normal Dana pump synchronization commands.
Potentially affected operations include:
syncPump
updateInitialState
syncUserOptions
syncHistory
fetchPumpTime
- temp basal communication
- bolus communication
Suspected cause
Looking at ContinousBluetoothManager.swift, handleBackgroundTask() appears to create an unstructured Task that periodically calls keepConnectionAlive() while the pump is connected.
However, the background Task does not appear to be stored in a property and explicitly cancelled before another background task is created after reconnect.
A possible sequence therefore seems to be:
Task A starts
↓
Task A sleeps between keep-alive calls
↓
Pump disconnects
↓
Pump reconnects
↓
Task B is created
↓
Task A wakes after the pump is connected again
↓
Task A sees isConnected == true
↓
Task A continues + Task B continues
↓
Two keep-alive tasks now exist
After another disconnect/reconnect:
and so on.
This would explain the observed progression:
2 → 3 → 4 → 5 → 6
simultaneous keep-alive calls after repeated reconnects.
Why this may produce "A command is already running"
PeripheralManager appears to allow only one outstanding pump command at a time.
If one command already owns the command/write queue, another command results in:
A command is already running
Therefore, if multiple keep-alive background tasks exist simultaneously, they may compete for the same command channel.
They may also compete with real pump operations such as synchronization or dosing-related communication.
Impact
During the affected period I observed:
- Multiple simultaneous keep-alive calls
- Repeated
A command is already running
- Repeated keep-alive failures
No connected device
- Repeated disconnect timeouts
- Automatic reconnect cycles
- Pump synchronization failures
- Communication failures around dosing operations
- Failed/stuck Loop cycles
- An extended period where normal closed-loop operation could not continue
CGM data remained available during the affected period.
Therefore, the Loop failure appeared to be related to Dana pump communication rather than missing CGM data.
Possible fix / question
Would it make sense for ContinousBluetoothManager to maintain exactly one keep-alive background Task?
For example, conceptually:
private var keepAliveTask: Task<Void, Never>?
Before creating a new task:
Then create/store the new task:
keepAliveTask = Task {
while !Task.isCancelled && isConnected {
keepConnectionAlive()
try? await Task.sleep(
nanoseconds: 60_000_000_000
)
}
}
The task could also be explicitly cancelled when the pump disconnects:
keepAliveTask?.cancel()
keepAliveTask = nil
before starting another keep-alive task after reconnect.
It may also be worth ensuring that keep-alive cannot compete with an active pump synchronization or dosing command.
Important
I have not tested the proposed code modification on a real pump.
The suggested fix above is only intended to illustrate the suspected lifecycle problem.
The suspected root cause is based on:
- The observed log pattern
- The increasing number of simultaneous keep-alive calls
- Repeated reconnect cycles
A command is already running errors
- The current Continuous Bluetooth background-task structure
The particularly interesting evidence is that the number of simultaneous keep-alive calls increases progressively:
2 → 3 → 4 → 5 → 6
after successive reconnects.
This seems unlikely to be caused by normal Bluetooth signal loss alone.
Environment
- Pump: Dana
- Connection mode: Continuous Bluetooth
- App: Loop / DanaKit
- Encryption mode observed: RSv3
- Date observed: 2026-08-13
Raw logs are not attached because they contain pump/Bluetooth identifiers.
I can provide additional sanitized log excerpts if needed.
Describe the bug
When using DanaKit in Continuous Bluetooth mode, repeated disconnect/reconnect cycles appear to accumulate multiple concurrent keep-alive background tasks.
After several reconnect cycles, multiple
keepConnectionAlive()calls begin occurring at exactly the same timestamp.These calls then produce repeated:
A command is already runningerrors, followed by disconnect timeouts, connection loss, automatic reconnects, pump synchronization failures, and eventually failed/stuck Loop cycles.
In my case, Loop later experienced an extended period where normal closed-loop operation could not continue.
Strong pattern observed in the logs
The most interesting observation is that the number of simultaneous
keepConnectionAlive()calls appears to increase after every reconnect cycle.Observed sequence:
This looks like an old background keep-alive task may remain alive after reconnect, while a new task is created.
The resulting pattern is approximately:
disconnect → reconnect → +1 keep-alive task → disconnect → reconnect → +1 keep-alive taskEventually multiple keep-alive tasks execute at the same time.
Example log
At 00:11:29, five keep-alive calls were triggered at essentially the same time:
Immediately afterwards:
Then the Bluetooth connection times out:
One second later the pump reconnects:
The same pattern repeats
At 00:13:37, six keep-alive calls were triggered at the same timestamp.
They were immediately followed by multiple:
A command is already runningerrors, followed by:
Failed to disconnect: The connection has timed out unexpectedly.and:
No connected deviceThe pump then reconnects again.
This pattern repeats continuously.
Multiple background jobs also appear in the log
At another point the log contains multiple messages like:
at the same timestamp.
This seems consistent with multiple background tasks existing simultaneously.
Additional command contention after reconnect
Another reconnect sequence shows several operations being started at almost exactly the same time:
Immediately afterwards the following operations fail:
This suggests that the keep-alive/background tasks may not only compete with each other, but also with normal Dana pump synchronization commands.
Potentially affected operations include:
syncPumpupdateInitialStatesyncUserOptionssyncHistoryfetchPumpTimeSuspected cause
Looking at
ContinousBluetoothManager.swift,handleBackgroundTask()appears to create an unstructuredTaskthat periodically callskeepConnectionAlive()while the pump is connected.However, the background Task does not appear to be stored in a property and explicitly cancelled before another background task is created after reconnect.
A possible sequence therefore seems to be:
After another disconnect/reconnect:
and so on.
This would explain the observed progression:
2 → 3 → 4 → 5 → 6simultaneous keep-alive calls after repeated reconnects.
Why this may produce "A command is already running"
PeripheralManagerappears to allow only one outstanding pump command at a time.If one command already owns the command/write queue, another command results in:
A command is already runningTherefore, if multiple keep-alive background tasks exist simultaneously, they may compete for the same command channel.
They may also compete with real pump operations such as synchronization or dosing-related communication.
Impact
During the affected period I observed:
A command is already runningNo connected deviceCGM data remained available during the affected period.
Therefore, the Loop failure appeared to be related to Dana pump communication rather than missing CGM data.
Possible fix / question
Would it make sense for
ContinousBluetoothManagerto maintain exactly one keep-alive background Task?For example, conceptually:
Before creating a new task:
Then create/store the new task:
The task could also be explicitly cancelled when the pump disconnects:
before starting another keep-alive task after reconnect.
It may also be worth ensuring that keep-alive cannot compete with an active pump synchronization or dosing command.
Important
I have not tested the proposed code modification on a real pump.
The suggested fix above is only intended to illustrate the suspected lifecycle problem.
The suspected root cause is based on:
A command is already runningerrorsThe particularly interesting evidence is that the number of simultaneous keep-alive calls increases progressively:
2 → 3 → 4 → 5 → 6after successive reconnects.
This seems unlikely to be caused by normal Bluetooth signal loss alone.
Environment
Raw logs are not attached because they contain pump/Bluetooth identifiers.
I can provide additional sanitized log excerpts if needed.