Electronics Design AU
MatterESP32Solved

ESP32 Matter device advertises fine over BLE but commissioning fails every time — stale QR code after a firmware rebuild?

5 min read3 replies
Original Question

Asked by stale_biscuit_03 ·

Bringing up my first Matter product on an ESP32-C6 using esp-matter (built on ESP-IDF 5.2). It's a basic on/off light accessory for now, just trying to get commissioning working before I build out the real cluster logic.

BLE side looks fine — I can see the device advertising in nRF Connect app with the right service UUID, and when I scan the printed QR code with the Apple Home app it finds the device immediately and starts the pairing flow. But every single time it fails partway through with something like "Additional Setup" or "Accessory Not Added" after a short delay — never gets to the point of asking which room to assign it to.

Things I've tried:

  • Re-scanning the QR code multiple times, same result
  • Deleting and re-adding in Apple Home
  • Rebooting the ESP32 between attempts
  • Confirmed the device is in "not commissioned" state via chip-tool reading GeneralCommissioning cluster — RegulatoryConfig reads back but commissioning never sticks

One detail that might be relevant: I changed one of the endpoint definitions (added a second On/Off cluster) and did a full rebuild + reflash yesterday. The QR code sticker on the dev board is from when I first flashed it two weeks ago — didn't think that mattered since I didn't touch the Wi-Fi credentials or anything network-related. Is the sticker actually tied to the firmware build somehow?

From the knowledge baseWhat Is Matter?

3 Replies

esp_idf_enjoyer
Accepted Answer

Yes — that's almost certainly your problem, and it's a really common one on esp-matter once you start rebuilding firmware after the first flash.

The QR code and the 11-digit manual pairing code both encode the same three values: discriminator, passcode (the SPAKE2+ setup PIN), and a product identification pair (VID/PID). These aren't discovered dynamically at commissioning time — they're baked into the firmware's onboarding payload, either from CONFIG_CHIP_DEVICE_DISCRIMINATOR / CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE in your sdkconfig, or from the factory partition if you're using esp-matter's factory data provider. The commissioner (Apple Home in your case) reads the QR code once, extracts those values, and uses the discriminator to filter which BLE advertisement to connect to and the passcode to verify the PASE session (the SPAKE2+ key exchange that establishes the initial secure channel before any cluster data is exchanged).

Here's the part that bites people: esp-matter's default sdkconfig in a lot of example projects has CONFIG_CHIP_DEVICE_GENERATE_RANDOM_DISCRIMINATOR (or an equivalent random-passcode default) enabled unless you've explicitly pinned fixed values. If that's set, every clean build generates a new discriminator and/or passcode, even if you only changed unrelated application code like your endpoint definitions. Your two-week-old printed QR code now encodes a discriminator/passcode pair that doesn't match what's actually running on the chip. Apple Home connects to a BLE advertisement matching the old discriminator if one happens to still be broadcast, or — more likely in your case — finds no matching discriminator, falls back to a slower discovery path, eventually connects to the actual device, and then fails PASE because the passcode doesn't match. That failure mode looks exactly like what you're describing: gets partway through, then silently drops with a generic error instead of a clear "wrong code" message.

Fix, two parts:

  1. Pin fixed values for development so this stops happening on every rebuild:
CONFIG_CHIP_DEVICE_GENERATE_RANDOM_DISCRIMINATOR=n
CONFIG_CHIP_DEVICE_DISCRIMINATOR=0xF00
CONFIG_CHIP_DEVICE_GENERATE_RANDOM_PASSCODE=n
CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE=20202021

(Those are the common esp-matter example defaults — don't ship a production unit with a shared example passcode, but they're fine for dev boards.)

  1. Regenerate the QR code and manual pairing code to match whatever discriminator/passcode you land on, using the chip-tool payload generate-qrcode command (or the online QR generator in the Matter SDK tools) — don't reuse a printed sticker across firmware revisions unless you've confirmed the values are pinned and unchanged.

Once the values are pinned, you only need to regenerate the code once per project, not per build — that's the whole point of fixing them. For the conceptual side of what's actually happening during commissioning (QR code → BLE discovery → PASE → network credentials → CASE), see what is Matter? — the commissioning section covers the full sequence this bug interrupts partway through.

zephyr_devotee

Can confirm this exact class of bug shows up on the nRF Connect SDK Matter samples too, not just esp-matter — same root cause, different Kconfig names (CONFIG_CHIP_DEVICE_DISCRIMINATOR and CONFIG_CHIP_DEVICE_SPAKE2_PASSCODE are shared across both SDKs since they both sit on the same open-source Matter/CHIP stack underneath). If you're doing Thread-transport Matter on an nRF5340 instead of Wi-Fi-transport on the ESP32, watch for exactly the same "printed code goes stale after a rebuild" trap.

One thing worth adding: double-check the discriminator length. It's a 12-bit value (0–4095), and I've seen people hand-edit a discriminator into their sdkconfig/prj.conf and accidentally set a value out of range, which some builds will silently truncate rather than error on. If BLE discovery seems to connect to something but PASE still fails even after regenerating the QR code, check the actual discriminator being advertised — you can read it back with chip-tool payload parse-setup-payload <your-qr-code-string> and compare it against what a BLE scanner (nRF Connect, or chip-tool discover commissionables) reports the device is actually advertising. They should match exactly.

ble_mesh_maven

Worth flagging a related but distinct failure mode in case anyone hits this thread with a similar-looking symptom: if commissioning appears to complete — Apple Home actually gets to the "select a room" screen or further — but the device is gone from the ecosystem after the next power cycle, that's not a discriminator/passcode problem, it's a fabric credential persistence problem. The device needs to commit its fabric table (operational certificates, keys, the CASE session material) to non-volatile storage — NVS on ESP32, the settings subsystem on Zephyr/NCS — before it's safe to reboot. If your commissioning flow or provisioning app logic triggers a reboot immediately after receiving a "commissioning complete" callback, and the NVS write hasn't actually been committed/flushed yet, the device comes back up with no fabric and looks "uncommissioned" again even though the app thinks it succeeded.

Different symptom, different fix (make sure the commit happens and is confirmed before any reboot in your provisioning sequence, and don't reboot from inside the commissioning complete callback itself), but easy to conflate with a PASE failure if you're only looking at "did commissioning finish" rather than "did it survive a power cycle." Worth ruling in or out early, since the diagnostic paths are completely different — one's a QR code problem, the other's a storage timing problem.

Related Discussions