Answers checklist
Which component are you using?
network_provisioning
ESP-IDF version
v5.3.2
Development Kit
Custom ESP32-S3 board
Used Component version
espressif/network_provisioning 1.0.2 (defect verified still present on master / 1.2.4 — see below)
Bug: update_wifi_scan_results() reports an empty scan collection as success, and silently drops SCAN_DONE events
In src/manager.c, update_wifi_scan_results() has two related issues that make a failed/racy Wi-Fi scan during provisioning indistinguishable from a genuine "no networks in range" result. Downstream, the provisioning app is told the scan succeeded with zero APs, so the user sees an empty network list instead of an error, dead-ending BLE provisioning.
This code is unchanged between 1.0.2 and current master (1.2.4), so both points below reproduce on the latest release. Line numbers below are from 1.0.2.
1. An empty collection is returned as ESP_OK.
static esp_err_t update_wifi_scan_results(void)
{
...
if (esp_wifi_scan_get_ap_num(&count) != ESP_OK) {
ESP_LOGE(TAG, "Failed to get count of scanned APs");
goto exit; // ret == ESP_FAIL
}
if (!count) {
ESP_LOGD(TAG, "Scan result empty");
ret = ESP_OK; // <-- empty == success
goto exit;
}
...
}
count == 0 from esp_wifi_scan_get_ap_num() is treated as a successful "no networks" result. But the same zero count is also produced when the scan never actually collected anything — e.g. a scan started before the radio/scan machinery was ready. Because it returns ESP_OK, the caller and the provisioning protocomm handler cannot tell "genuinely no APs in range" from "the scan failed to collect results." The app-facing result is an empty AP list with a success status, which surfaces to the user as "no networks found."
2. A SCAN_DONE event that arrives when prov_ctx->scanning is false is dropped.
static esp_err_t update_wifi_scan_results(void)
{
if (!prov_ctx->scanning) {
return ESP_ERR_INVALID_STATE; // <-- SCAN_DONE silently discarded
}
...
}
If a WIFI_EVENT_SCAN_DONE is delivered when the manager does not believe it is scanning (a state/timing race around scan start/stop), the collected result is discarded with no retry and no signal to the provisioning flow — another path to a lost/empty scan result.
Field evidence
Found via AI-assisted hardware-in-the-loop testing (co-authored with Claude). We ran a headless BLE-provisioning probe that repeatedly issues the scan_wifi_APs command right after the device enters provisioning mode:
- 9 scan attempts, 3 returned empty, in an environment with multiple strong APs consistently visible to the same device outside provisioning.
- Empty and populated scans took an identical ~5.25s. That is the duration of a full sequential 14-channel sweep, so the empty results are every channel collected empty, not a truncated or aborted sweep.
The identical full-sweep duration for empty results points at a readiness/timing race: the scan is requested and runs to completion, but collects nothing on any channel — and that empty collection is then reported to the app as a successful zero-AP result via the ESP_OK path in (1). This intermittency (empty right after entering provisioning mode) is what makes it user-visible as a flaky "no networks found."
Suggested direction
- Distinguish an empty collection from a genuine zero-AP result — e.g. return a distinct error (or set a flag) on the empty path in (1) rather than
ESP_OK, so the provisioning handler can retry or report a scan failure instead of an empty list.
- Avoid silently dropping a SCAN_DONE that arrives while
!prov_ctx->scanning in (2) — at minimum log it; ideally still collect/retry so the result is not lost.
Because (1) changes the return semantics of update_wifi_scan_results() (which other callers/handlers depend on), we did not want to presume the fix shape. Happy to open a PR if you can confirm the preferred direction (distinct error code vs. an out-param/flag).
Transparency
This defect was root-caused with AI assistance (Claude) as part of hardware-in-the-loop testing of our own product firmware. The repro described above is exactly the headless ble_prov scan_wifi_APs probe we ran (9 scans, 3 empty, identical ~5.25s duration); we have not run any repro beyond that.
Answers checklist
idf_component.yml.Which component are you using?
network_provisioningESP-IDF version
v5.3.2
Development Kit
Custom ESP32-S3 board
Used Component version
espressif/network_provisioning1.0.2 (defect verified still present onmaster/ 1.2.4 — see below)Bug:
update_wifi_scan_results()reports an empty scan collection as success, and silently drops SCAN_DONE eventsIn
src/manager.c,update_wifi_scan_results()has two related issues that make a failed/racy Wi-Fi scan during provisioning indistinguishable from a genuine "no networks in range" result. Downstream, the provisioning app is told the scan succeeded with zero APs, so the user sees an empty network list instead of an error, dead-ending BLE provisioning.This code is unchanged between 1.0.2 and current
master(1.2.4), so both points below reproduce on the latest release. Line numbers below are from 1.0.2.1. An empty collection is returned as
ESP_OK.count == 0fromesp_wifi_scan_get_ap_num()is treated as a successful "no networks" result. But the same zero count is also produced when the scan never actually collected anything — e.g. a scan started before the radio/scan machinery was ready. Because it returnsESP_OK, the caller and the provisioning protocomm handler cannot tell "genuinely no APs in range" from "the scan failed to collect results." The app-facing result is an empty AP list with a success status, which surfaces to the user as "no networks found."2. A SCAN_DONE event that arrives when
prov_ctx->scanningis false is dropped.If a
WIFI_EVENT_SCAN_DONEis delivered when the manager does not believe it is scanning (a state/timing race around scan start/stop), the collected result is discarded with no retry and no signal to the provisioning flow — another path to a lost/empty scan result.Field evidence
Found via AI-assisted hardware-in-the-loop testing (co-authored with Claude). We ran a headless BLE-provisioning probe that repeatedly issues the
scan_wifi_APscommand right after the device enters provisioning mode:The identical full-sweep duration for empty results points at a readiness/timing race: the scan is requested and runs to completion, but collects nothing on any channel — and that empty collection is then reported to the app as a successful zero-AP result via the
ESP_OKpath in (1). This intermittency (empty right after entering provisioning mode) is what makes it user-visible as a flaky "no networks found."Suggested direction
ESP_OK, so the provisioning handler can retry or report a scan failure instead of an empty list.!prov_ctx->scanningin (2) — at minimum log it; ideally still collect/retry so the result is not lost.Because (1) changes the return semantics of
update_wifi_scan_results()(which other callers/handlers depend on), we did not want to presume the fix shape. Happy to open a PR if you can confirm the preferred direction (distinct error code vs. an out-param/flag).Transparency
This defect was root-caused with AI assistance (Claude) as part of hardware-in-the-loop testing of our own product firmware. The repro described above is exactly the headless
ble_provscan_wifi_APsprobe we ran (9 scans, 3 empty, identical ~5.25s duration); we have not run any repro beyond that.