Troubleshooting
The library logs at INFO by default. Look for tags starting with scd. — scd.identity, scd.edge, scd.mqtt, scd.heartbeat, scd.ota — plus the top-level scadable tag. For DEBUG-level output, set CONFIG_SCD_DEBUG_VERBOSE in idf.py menuconfig.
Match your symptom against the headings below.
"identity load failed" at boot
E (...) scd.identity: nvs_open("scadable_cfg") failed: ESP_ERR_NVS_NOT_FOUND
E (...) scadable: identity load failed — device is unprovisioned or was
flashed with the wrong NVS bundle. Halting library bootstrap;
customer code will still run.
Cause. The NVS partition has no SCADABLE credential bundle. Either the device was never provisioned, or esptool erase_flash wiped the partition, or the wrong artifact was flashed.
Fix. Provision via the SCADABLE dashboard, then use the browser flasher to write the bundle. The flasher writes both firmware (to ota_0) and the NVS bundle (to offset 0x9000). After re-flash, the boot succeeds.
If you've already provisioned but erased the chip, you need to re-flash the NVS bundle — firmware alone isn't enough.
Device boots but never goes online
I (...) scadable: libscadable v0.1.0 starting
I (...) scd.identity: identity loaded: cn=SC-... device_id=...
W (...) scadable: scadable_user_main not defined — running headless ...
Cause. You didn't define scadable_user_main, or your function doesn't bring up the network.
Fix. Define scadable_user_main and call your Wi-Fi (or Ethernet, or cellular) setup from inside it. The library is event-driven — it waits for IP_EVENT_*_GOT_IP. If nothing brings up an IP, the library never advances past dormant.
See the quickstart for a complete Wi-Fi STA example.
"edge route failed; falling back to NVS default"
W (...) scd.edge: perform: ESP_ERR_HTTP_CONNECT
W (...) scadable: edge route failed; falling back to NVS default
mqtt-yyz.scadable.com:8883
Cause. The HTTPS GET to edge.scadable.com/v1/route failed — DNS lookup, TLS handshake, or general network unreachability.
Diagnosis.
- Can the device resolve
edge.scadable.com? Tryping edge.scadable.comfrom a laptop on the same Wi-Fi. - Is the device's clock approximately right? TLS handshake fails if the device clock is wildly off (e.g. epoch 0). The library doesn't run NTP itself; ESP-IDF generally syncs SNTP from the AP if available.
- Is your network blocking outbound HTTPS to Cloudflare IPs?
Behavior. This is a warning, not a hard failure. The library falls back to the mqtt_host + mqtt_port baked into NVS at provision time and proceeds. Region-switching from the dashboard won't take effect until the edge call recovers.
"no mqtt_host in response"
W (...) scd.edge: no mqtt_host in response: ...
Cause. The HTTPS GET succeeded but the response body wasn't the expected shape (or was > 512 bytes and got truncated).
Fix.
- Confirm
CONFIG_SCD_EDGE_URLpoints at a real SCADABLE edge endpoint. The default ishttps://edge.scadable.com/v1/route. - If you've pointed at a dev backend, confirm its
/v1/routereturns:{ "mqtt_host": "...", "mqtt_port": 8883, "region": "yyz", "version": 1 }
MQTT connects then immediately disconnects
I (...) scd.mqtt: connected
W (...) scd.mqtt: disconnected
I (...) scd.mqtt: connected
W (...) scd.mqtt: disconnected
Common causes:
- CA chain mismatch. The CA in NVS doesn't validate the broker's cert. Re-provision to refresh.
- Two devices with the same CN. Each device must have a unique provisioning bundle. Two devices connecting with the same
client_id(which equals the cert CN) will boot each other off the broker. - Flaky network. Keepalive drops on weak Wi-Fi. The library auto-reconnects; persistent disconnects suggest a network issue, not a library issue.
OTA command received but download fails
I (...) scd.ota: command received: 0.1.1
I (...) scd.ota: starting OTA version=0.1.1 url=...
E (...) scd.ota: ota_begin: ESP_FAIL
Common causes:
- Partition table missing OTA slots. Your
partitions.csvmust haveota_0,ota_1, andotadatapartitions. ESP-IDF'spartitions_two_ota.csvworks as-is. - OTA URL not reachable. Same diagnosis as for the edge endpoint — DNS, TLS, network.
- Image too big. Firmware exceeds the
ota_0partition size. Either shrink the firmware (optimize for size in menuconfig) or grow the partitions inpartitions.csv.
Heartbeats stop appearing on the dashboard
The first thing to check is the device's serial — is it still printing heartbeat logs every 30s?
I (...) scd.heartbeat: publish skipped: ESP_ERR_INVALID_STATE
That's the library detecting MQTT disconnected and skipping the publish. Normal during a reconnect; persistent means MQTT is genuinely down — see MQTT connects then immediately disconnects above.
If the device looks fine on serial but the dashboard isn't showing heartbeats, check:
- Is the device on the namespace you're looking at? (Devices are scoped to namespaces.)
- Is the namespace's broker the one the device is connected to? (Multi-region setups have multiple brokers.)
Code compiles locally but fails on the SCADABLE build
The SCADABLE build pipeline uses a recent ESP-IDF. If you're developing against an older version (5.0 or earlier), some headers differ. The library targets ESP-IDF ≥ 5.1, declared in idf_component.yml. Upgrade your local ESP-IDF to match.
How to get more detail
Enable verbose logging in idf.py menuconfig:
Component config → SCADABLE Gateway → [*] Verbose logging
You can also bump ESP-IDF's own log levels:
Component config → Log → Default log verbosity → Debug
That floods the console — useful for one-off diagnosis, not for production.
Still stuck
- Capture the full
idf.py monitoroutput from boot. - Note your ESP-IDF version (
idf.py --version) and chip target. - File an issue at https://github.com/scadable/gateway-esp/issues with the serial log + your
.scadable/config.yaml+ yourpartitions.csv.
