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. |
A call in your code no longer exists, such as stopPublishAudio() | The API changed before 1.0. 0.3.1 removed the stop calls, 0.3.0 changed startPublishAudio(). | Check Release Notes for the version you pulled, and use leave() to tear a session down. |
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 7. |
| 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 board resets in a loop, with a brownout message in the log | The USB port or cable cannot supply enough current, which the Korvo-2 is more sensitive to. | Use a powered port or a better cable, and keep CONFIG_ESP_PHY_REDUCE_TX_POWER=y. |
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 meeting ID is not set, and the app returns early | menuconfig -> VideoSDK Configuration was never filled in. | Set the auth token and the meeting ID there. They live in sdkconfig, not in source. |
init returns 3001 or 3002 | TLS or HTTP to the VideoSDK server failed. | Confirm Wi-Fi is up and DNS resolves, and that the mbedTLS certificate bundle options are still set. Retry with a delay. |
init returns 3011 or 3015 | The peer connection never came up. | Verify the token is valid and unexpired, that the meeting 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. |
init returns 3010 | The audio codec could not be initialized on this board. | Try another init_config_t.audioCodec (AUDIO_CODEC_PCMA, AUDIO_CODEC_PCMU or AUDIO_CODEC_OPUS). |
init returns 3006 | Board or audio codec hardware initialization failed. | Confirm the board selected under menuconfig -> SET Microcontroller matches the hardware you are flashing. |
| 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

