NimBLE crash during rapid Wi-Fi provisioning stop/start sequence (protocomm_ble_stop)
Posted: Mon Feb 09, 2026 2:30 pm
ESP-IDF Version
- Observed on multiple ESP-IDF–based firmware releases
- NimBLE used as BLE stack
- Issue reproducible across different firmware versions built on ESP-IDF
Hardware
- ESP32-S3 Wroom1 (R16N8)
- Full production hardware (no special debug configuration)
Description
- We are encountering a crash in NimBLE during Wi-Fi provisioning when BLE provisioning is stopped and restarted in quick succession.
- The crash occurs inside protocomm_ble_stop(), even though the provisioning context pointer passed to it is confirmed to be non-NULL at the time of invocation.
- The issue appears to be timing-sensitive and related to rapid provisioning state transitions.
Reproduction Steps
- The issue does not reproduce reliably unless commands are executed back-to-back with no delay.
- While Wi-Fi provisioning is on, trigger clear Wi-Fi credentials(Which stops and starts BLE provisioning) multiple times consecutively (e.g., 3–5 times) with no delay between commands.
Expected Behavior
- BLE provisioning should stop and restart cleanly without crashing, even if provisioning commands are issued rapidly.
Actual Behavior
- A crash occurs inside the NimBLE stack during BLE provisioning shutdown.
Call Stack (Observed)
wifi_prov_mgr_stop_provisioning()
→ wifi_prov_mgr_stop_service()
→ xTaskCreateStatic(prov_stop_task, ...)
→ prov_stop_task()
→ prov_ctx->mgr_config.scheme.prov_stop(prov_ctx->pc)
→ protocomm_ble_stop() <-- crash occurs here
Additional Details
- A NULL check is already present before invoking:
Code: Select all
prov_ctx->mgr_config.scheme.prov_stop(prov_ctx->pc)
- prov_ctx->pc is confirmed to be non-NULL at runtime.
- The failure occurs internally within
Code: Select all
protocomm_ble_stop()
.
- The issue is reproducible across multiple firmware builds.
- The crash is highly timing-dependent; adding delays between commands often prevents reproduction.
Questions / Guidance Requested
- Are there known race conditions or reentrancy issues in protocomm_ble_stop() when called rapidly?
- Is there a recommended synchronization or state-check mechanism before stopping BLE provisioning?
- Are there known limitations when stopping/starting BLE provisioning multiple times in quick succession using NimBLE?
- Any guidance or pointers on safely handling rapid provisioning state transitions would be greatly appreciated.
LOG Snippet:
PASS LOG(NO CRASH)
I (182647) NimBLE: GAP procedure initiated: stop advertising.
I (182651) NimBLE: GAP procedure initiated: stop advertising.
I (182658) wifi_prov_mgr: Provisioning stopped
D (182658) wifi_prov_mgr: execute_event_cb : 5
I (182659) WIFI_CONFIG: WiFi provisioning ended.
D (182659) wifi_prov_mgr: Provisioning not running
D (182659) wifi_prov_mgr: execute_event_cb : 6
I (182659) WIFI_CONFIG: WiFi provisioning manager deinit.
FAIL LOG(NO CRASH)
I (1157550) WIFI_CONFIG: Provisioning has been stopped.
D (1157550) wifi_prov_mgr: Stopping provisioning
D (1157551) wifi_prov_mgr: Provisioning scheduled for stopping
Available internal heap: 57839 bytes
Internal heap utilization: 81%
Available external (SPI RAM) heap: 3135628 bytes
Available heap (internal + external): 3169844 bytes
Available largest contiguous block in internal heap: 22528 bytes
Minimum heap that has ever been available: 3123104 bytes
I (1167552) NimBLE: GAP procedure initiated: stop advertising.
I (1167621) NimBLE: GAP procedure initiated: stop advertising.
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x3a (SPI_FAST_FLASH_BOOT)
Saved PC:0x40375c85
SPIWP:0xee
mode:DIO, clock div:2
load:0x3fce3980,len:0x1d50
load:0x403c9700,len:0x4
load:0x403c9704,len:0xb24
load:0x403cc700,len:0x42bc
entry 0x403c9898
- Observed on multiple ESP-IDF–based firmware releases
- NimBLE used as BLE stack
- Issue reproducible across different firmware versions built on ESP-IDF
Hardware
- ESP32-S3 Wroom1 (R16N8)
- Full production hardware (no special debug configuration)
Description
- We are encountering a crash in NimBLE during Wi-Fi provisioning when BLE provisioning is stopped and restarted in quick succession.
- The crash occurs inside protocomm_ble_stop(), even though the provisioning context pointer passed to it is confirmed to be non-NULL at the time of invocation.
- The issue appears to be timing-sensitive and related to rapid provisioning state transitions.
Reproduction Steps
- The issue does not reproduce reliably unless commands are executed back-to-back with no delay.
- While Wi-Fi provisioning is on, trigger clear Wi-Fi credentials(Which stops and starts BLE provisioning) multiple times consecutively (e.g., 3–5 times) with no delay between commands.
Expected Behavior
- BLE provisioning should stop and restart cleanly without crashing, even if provisioning commands are issued rapidly.
Actual Behavior
- A crash occurs inside the NimBLE stack during BLE provisioning shutdown.
Call Stack (Observed)
wifi_prov_mgr_stop_provisioning()
→ wifi_prov_mgr_stop_service()
→ xTaskCreateStatic(prov_stop_task, ...)
→ prov_stop_task()
→ prov_ctx->mgr_config.scheme.prov_stop(prov_ctx->pc)
→ protocomm_ble_stop() <-- crash occurs here
Additional Details
- A NULL check is already present before invoking:
Code: Select all
prov_ctx->mgr_config.scheme.prov_stop(prov_ctx->pc)
- prov_ctx->pc is confirmed to be non-NULL at runtime.
- The failure occurs internally within
Code: Select all
protocomm_ble_stop()
.
- The issue is reproducible across multiple firmware builds.
- The crash is highly timing-dependent; adding delays between commands often prevents reproduction.
Questions / Guidance Requested
- Are there known race conditions or reentrancy issues in protocomm_ble_stop() when called rapidly?
- Is there a recommended synchronization or state-check mechanism before stopping BLE provisioning?
- Are there known limitations when stopping/starting BLE provisioning multiple times in quick succession using NimBLE?
- Any guidance or pointers on safely handling rapid provisioning state transitions would be greatly appreciated.
LOG Snippet:
PASS LOG(NO CRASH)
I (182647) NimBLE: GAP procedure initiated: stop advertising.
I (182651) NimBLE: GAP procedure initiated: stop advertising.
I (182658) wifi_prov_mgr: Provisioning stopped
D (182658) wifi_prov_mgr: execute_event_cb : 5
I (182659) WIFI_CONFIG: WiFi provisioning ended.
D (182659) wifi_prov_mgr: Provisioning not running
D (182659) wifi_prov_mgr: execute_event_cb : 6
I (182659) WIFI_CONFIG: WiFi provisioning manager deinit.
FAIL LOG(NO CRASH)
I (1157550) WIFI_CONFIG: Provisioning has been stopped.
D (1157550) wifi_prov_mgr: Stopping provisioning
D (1157551) wifi_prov_mgr: Provisioning scheduled for stopping
Available internal heap: 57839 bytes
Internal heap utilization: 81%
Available external (SPI RAM) heap: 3135628 bytes
Available heap (internal + external): 3169844 bytes
Available largest contiguous block in internal heap: 22528 bytes
Minimum heap that has ever been available: 3123104 bytes
I (1167552) NimBLE: GAP procedure initiated: stop advertising.
I (1167621) NimBLE: GAP procedure initiated: stop advertising.
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x3a (SPI_FAST_FLASH_BOOT)
Saved PC:0x40375c85
SPIWP:0xee
mode:DIO, clock div:2
load:0x3fce3980,len:0x1d50
load:0x403c9700,len:0x4
load:0x403c9704,len:0xb24
load:0x403cc700,len:0x42bc
entry 0x403c9898