Environment
NimBLE-Arduino 2.3.9
ESP32 (Arduino Core 3.3.7)
Host: iOS (confirmed); likely affects others too
Security mode: Passkey (MITM + SC + Bond)
Behaviour
After calling NimBLEDevice::deleteAllBonds(), attempting to re-pair within the same boot cycle fails consistently. The passkey is generated and displayed correctly, the pairing prompt appears, but pairing immediately fails with onPairingComplete(false). The device loops in connect/fail/disconnect endlessly. Any reboot of the ESP32 clears the problem and the first pairing attempt after boot always succeeds — but only once.
Possible Cause
deleteAllBonds() calls ble_store_clear() internally, which wipes the NVS bond records but apparently does not flush the NimBLE Security Manager's in-memory per-peer state. The stale SM context causes the pairing handshake to fail when device attempts to re-pair against the same peer address within the same session.
Workaround
Instead of calling deleteAllBonds(), iterate in reverse through all bonded peers and call deleteBond() on each individually. deleteBond() routes through ble_gap_unpair() and seems to flush properly. Reverse iteration avoids index-shift issues as entries are removed.
int numBonds = NimBLEDevice::getNumBonds();
for (int i = numBonds - 1; i >= 0; i--) {
NimBLEDevice::deleteBond(NimBLEDevice::getBondedAddress(i));
}
This workaround was confirmed to resolve iOS re-pairing failure within the same boot cycle. The fix likely applies to other environments as well, though not tested.
Suggestion
deleteAllBonds() itself could be updated to use this loop internally instead of calling ble_store_clear() directly, so callers get correct SM state cleanup without needing to work around it manually.
Environment
NimBLE-Arduino 2.3.9
ESP32 (Arduino Core 3.3.7)
Host: iOS (confirmed); likely affects others too
Security mode: Passkey (MITM + SC + Bond)
Behaviour
After calling
NimBLEDevice::deleteAllBonds(), attempting to re-pair within the same boot cycle fails consistently. The passkey is generated and displayed correctly, the pairing prompt appears, but pairing immediately fails with onPairingComplete(false). The device loops in connect/fail/disconnect endlessly. Any reboot of the ESP32 clears the problem and the first pairing attempt after boot always succeeds — but only once.Possible Cause
deleteAllBonds()callsble_store_clear()internally, which wipes the NVS bond records but apparently does not flush the NimBLE Security Manager's in-memory per-peer state. The stale SM context causes the pairing handshake to fail when device attempts to re-pair against the same peer address within the same session.Workaround
Instead of calling
deleteAllBonds(), iterate in reverse through all bonded peers and calldeleteBond()on each individually.deleteBond()routes throughble_gap_unpair()and seems to flush properly. Reverse iteration avoids index-shift issues as entries are removed.This workaround was confirmed to resolve iOS re-pairing failure within the same boot cycle. The fix likely applies to other environments as well, though not tested.
Suggestion
deleteAllBonds()itself could be updated to use this loop internally instead of callingble_store_clear()directly, so callers get correct SM state cleanup without needing to work around it manually.