Troubleshooting - IoT SDK
Start from what you can see: the compiler error, the boot log, or the number a call returned. Each entry says what causes it and where the full explanation lives.
tip
Turn on debug logs before chasing anything runtime related. menuconfig -> VideoSDK Logging -> Debug, and check CONFIG_LOG_MAXIMUM_LEVEL_DEBUG=y is in your build. See Logging and Debugging.
The build fails
| Symptom | Cause | Fix |
|---|---|---|
Incompatible pointer type errors coming from srtp.c | On Xtensa with ESP-IDF 5.4.2+, uint32_t is long unsigned int while libsrtp uses unsigned int. Same width, but the compiler rejects the pointers. | Add the idf_component_get_property / target_compile_options lines to main/CMakeLists.txt. Without them the project does not build. See Quick Start, Step 3. |
| Build fails for a target other than ESP32-S3 | The SDK supports the ESP32-S3 only. | idf.py set-target esp32s3, then build again. |
| The app partition is too small for the binary | The default partition table does not fit the firmware. | Add partitions.csv and keep CONFIG_PARTITION_TABLE_CUSTOM=y. See Quick Start, Step 4. |
| Undefined references when linking the component | An early SDK release did not declare its own runtime dependencies. | Move to the current release. See Release Notes. |
Configuration does not take effect
| Symptom | Cause | Fix |
|---|---|---|
Values in sdkconfig.defaults are ignored | sdkconfig.defaults is read only on the first build, when no sdkconfig exists yet. | Delete the generated sdkconfig and build again. |
| Debug log verbosity is selected but nothing extra prints | The debug logs were never compiled into the image. | Keep CONFIG_LOG_MAXIMUM_LEVEL_DEBUG=y in sdkconfig.defaults, delete sdkconfig, rebuild. See Logging and Debugging. |
Free PSRAM reads 0 at runtime | PSRAM is not actually enabled, so every media buffer competes for internal RAM. | Confirm CONFIG_SPIRAM, CONFIG_SPIRAM_MODE_OCT and CONFIG_SPIRAM_SPEED_80M survived into sdkconfig, and that the board really has octal PSRAM. See Supported Microcontrollers. |
Flashing and the serial monitor
| Symptom | Cause | Fix |
|---|---|---|
| No such port, or you cannot tell which port is the board | The board enumerates differently per OS and per board. | List ports before and after plugging the board in. See Quick Start, Step 8. |
| Permission denied opening the port on Linux | Your user is not in the dialout group. | sudo usermod -a -G dialout $USER, then log out and back in. |
| The port is busy | Another monitor or serial tool still holds it. | Close the other session. Exit a running monitor with Ctrl+]. |
The device does not join
Check the number the call returned before guessing: it usually says which layer failed. Full table in Result Code.
| Symptom | Cause | Fix |
|---|---|---|
| The log says the token or room ID is not set, and the app returns early | menuconfig -> VideoSDK Configuration was never filled in. | Set the auth token and the room ID there. They live in sdkconfig, not in source. |
create_room() or a start* call returns 3001 or 3002 | TLS or HTTP to the VideoSDK server failed. init() does no network I/O, so these surface when a room is created or the first start* opens signaling. | Confirm Wi-Fi is up and DNS resolves, and that the mbedTLS certificate bundle options are still set. Retry with a delay. |
A start* call returns 3011 or 3015 | The peer connection never came up. | Verify the token is valid and unexpired, that the room ID exists, and that the network allows outbound UDP. |
A join returns 3020 | ICE found no working network path, typically guest Wi-Fi or a captive portal blocking UDP. | Test on a phone hotspot to confirm, then fix the network. |
A join returns 3021 | The DTLS handshake failed. | Retry. If it repeats, check free heap and that only one session is active on the device. |
Any *_MEMORY_ALLOC_FAILED, *_MUTEX_CREATE_FAILED or *_TASK_CREATE_FAILED | The device ran short of RAM rather than hitting a network problem. | Print the free heap and confirm PSRAM is on. See Logging and Debugging. |
A call returns 3023 | init() was not called first. | Call init() once, before any other SDK method. |
Audio or video is missing
| Symptom | Cause | Fix |
|---|---|---|
startSubscribeAudio() or startSubscribeVideo() returns 3004 | The board has no speaker or no display. Expected, not a failure. | Use a board with that hardware, such as the ESP32-S3-Korvo-2. See Supported Microcontrollers. |
| The device joins but other participants hear nothing | Publishing was never started, or it failed. | Check the return of startPublishAudio() in the log. |
| Nothing plays through the speaker | Volume is at zero, or the wrong board is selected. | Set the speaker volume in menuconfig -> SET Microcontroller, or call setSpeakerVolume() at runtime. |
startPublishAudio() or startSubscribeAudio() returns 3010 | The board's I2S/codec (mic or speaker) driver did not come up. | Confirm the board under menuconfig -> SET Microcontroller matches your hardware, check the mic or speaker is wired and responding, and check free internal RAM. |
init() (audio codec, Korvo-2) or a video start* call (camera/display) returns 3006 | Board hardware that should be present failed to start. | Confirm the board selected under menuconfig -> SET Microcontroller matches the hardware you are flashing, and that the camera ribbon is seated. |
| Video never appears | The device is audio-only, or the camera was not detected. | Set init_config_t.videoCodec to VIDEO_CODEC_JPEG and check the camera sensor options in sdkconfig.defaults. See Publish Video. |
It works, then stops
| Symptom | Cause | Fix |
|---|---|---|
| The call goes quiet after a while and never recovers | The signaling session dropped. Wi-Fi reconnects on its own, the session does not. | Register setConnectionStateHandler() and rejoin. See Connection State. |
| A device that ran for hours fails to rejoin | The token expired while the device was up. | Give long-lived devices a way to fetch a fresh token. See Authentication and Tokens. |
sendMessage() returns 3026 | The send queue is momentarily full. | Slow down, and retry shortly. See Send Message. |
sendMessage() returns 3025 | The channel was never opened. | Call startMessageChannel() once after init(). |
leave() returns 3018 or 3019 | Teardown never started, so the session is still active. | Free some memory and call leave() again. |
leave() returns 3022 | Teardown started but did not finish in 6 seconds. | Do not treat it as a clean exit and do not rejoin on top of it. Restart the device if it repeats. |
Still stuck
Collect the serial log with debug verbosity on, note the SDK version from your main/idf_component.yml and the ESP-IDF version printed at boot, then reach out:
Got a Question? Ask us on discord

