Result Code - IoT SDK
Every SDK call returns a result_t. RESULT_OK (0) means the operation succeeded; anything else tells you what went wrong and, in most cases, what to do about it. On a device there is no exception to catch and no user watching, so check the return of every call and log it.
result_t r = startPublishAudio();
if (r != RESULT_OK) {
ESP_LOGE("IOT-SDK", "startPublishAudio failed: %d", r);
}
How to read a failure
Codes fall into a few groups, and each group wants a different response.
- Expected on this hardware.
DEVICE_NOT_SUPPORTED(3004) from a subscribe call means the board has no speaker or no display. Not a failure, and retrying will not change it. See Supported Microcontrollers. - Wrong call order.
INIT_NOT_CALLED(3023),DATA_CHANNEL_NOT_STARTED(3025) andTASK_ALREADY_STARTED(3008) are programming errors. Fix the sequence rather than retrying. - Out of memory. The allocation, mutex and task-creation codes mean the device ran short of RAM. Check what is actually free before you retry. See Logging and Debugging.
- Network and transport.
SSL_CONNECT_FAILED(3001),CANDIDATE_PAIR_FAILED(3020) andDTLS_HANDSHAKE_FAILED(3021) mean the device could not reach or negotiate with the server. Retry with backoff, and suspect the network itself if they persist. - Session already gone. If the session dropped mid-call, rejoin instead of retrying the call that failed. See Connection State.
leave() is the one call whose failures need opposite responses. STOP_PUBLISH_TASK_CREATE_FAILED (3018) and STOP_SUBSCRIBE_TASK_CREATE_FAILED (3019) mean teardown never started and the session is still up, so call leave() again. LEAVE_FAILED (3022) means teardown got stuck, so do not treat it as a clean exit.
All result codes
Every SDK call returns a result_t. RESULT_OK (0) is success; every other value is a failure. Error codes run from 3001 to 3026.
Returned by lists the calls that produce each code. Codes 3009-3013 come from the shared sending connection, so a subscribe or message call can report them too.
Note: ESP-IDF reads sdkconfig.defaults only when no sdkconfig exists yet. To change a CONFIG_* setting, use idf.py menuconfig, or delete sdkconfig and rebuild.
| Enum Constant | Value | Returned by | Description |
|---|---|---|---|
RESULT_OK | 0 | every call | Success. |
SSL_CONNECT_FAILED | 3001 | create_room() | The device could not open a TLS connection to the VideoSDK API host on port 443. Check Wi-Fi is up, DNS resolves, and that outbound 443 is not blocked. If you set init_config_t.signalingBaseUrl, confirm the host is correct. |
HTTP_REQUEST_FAILED | 3002 | create_room(), start*, startMessageChannel() | A server request failed, or the signaling connection could not be opened. Check Wi-Fi, DNS, and that the token is valid and unexpired. Signaling verifies the server certificate, so also check CONFIG_MBEDTLS_CERTIFICATE_BUNDLE and CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL are set; a trimmed bundle cannot validate it. Retry with a delay. A start* call also reports this when the media connection stalls for 15 s (see 3020). |
MEMORY_ALLOC_FAILED | 3003 | create_room(), init(), startMessageChannel(), sendMessage() | Out of memory. The limit is internal RAM, not PSRAM, so check heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL) rather than the total free heap. Free memory, or stop a stream you are not using. |
DEVICE_NOT_SUPPORTED | 3004 | startSubscribeAudio(), startSubscribeVideo(), stopSubscribeAudio(), stopSubscribeVideo() | The board has no speaker or no display, so there is nothing to receive on. This is expected on the XIAO, not a failure (the stop* calls return it too, so the pairs stay symmetric). Hardware that should be present but fails to start reports 3006 instead. See Supported Microcontrollers. |
NULL_PARAMETER | 3005 | create_room(), init(), sendMessage() | A parameter was NULL, empty, or out of range: an empty token; a NULL roomId/token; a signalingBaseUrl with a port or path (it must be a bare host); or a sendMessage() longer than 24000 bytes. |
INIT_BOARD_FAILED | 3006 | init(), startPublishVideo(), startSubscribeVideo() | Board hardware that should be present failed to start: the audio codec from init() (Korvo-2 only), the camera from startPublishVideo(), or the display from startSubscribeVideo(). Reseat the camera ribbon and confirm the board under menuconfig -> SET Microcontroller matches your hardware. See Troubleshooting. |
PEER_INIT_FAILED | 3007 | init() | The media security layer (SRTP) failed to start, in practice from low memory at startup. Reduce what your app allocates before init(), and reboot. |
TASK_ALREADY_STARTED | 3008 | startPublishAudio(), startPublishVideo(), startSubscribeAudio(), startSubscribeVideo() | That stream is already running. Call the matching stop*, then start it again. You do not need to leave the room. |
PUBLISH_MUTEX_CREATE_FAILED | 3009 | any start*, startMessageChannel() | Could not create the publish lock; out of internal RAM. Free memory and retry. |
AUDIO_CODEC_INIT_FAILED | 3010 | startPublishAudio(), startSubscribeAudio() | The board's I2S/codec driver (mic or speaker) did not come up. Confirm the board under menuconfig -> SET Microcontroller matches your hardware. See Troubleshooting. |
PUBLISH_PEER_CONNECTION_FAILED | 3011 | any start*, startMessageChannel() | The sending connection could not be created. Verify the token is valid, the room ID exists, and the network allows outbound UDP. Retry with backoff. |
PUBLISH_MEMORY_ALLOC_FAILED | 3012 | any start*, startMessageChannel() | Could not allocate the send task's memory. Its stack comes from PSRAM and its small control block from internal RAM, so a failure here usually means PSRAM is short. Confirm octal PSRAM is enabled and check its free space, then check free internal RAM. If the memory allocates but the task will not start, that is 3013. |
PUBLISH_TASK_CREATE_FAILED | 3013 | any start*, startMessageChannel() | Could not create the sending task. The stack is already in PSRAM, so what ran out is internal RAM. Free memory, and confirm CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM is still set (the older alias CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY maps to it). |
SUBSCRIBE_MUTEX_CREATE_FAILED | 3014 | startSubscribeAudio(), startSubscribeVideo() | Could not create the subscribe lock; out of internal RAM. Free memory and retry. |
SUBSCRIBE_PEER_CONNECTION_FAILED | 3015 | startSubscribeAudio(), startSubscribeVideo() | The receiving connection could not be created. Verify the token is valid, the room ID exists, and the network allows outbound UDP. Retry with backoff. |
SUBSCRIBE_MEMORY_ALLOC_FAILED | 3016 | startSubscribeAudio(), startSubscribeVideo() | Could not allocate the receive task's memory. Same allocation shape as 3012 (the stack comes from PSRAM, the small control block from internal RAM), so check free PSRAM first, then free internal RAM. If the memory allocates but the task will not start, that is 3017. |
SUBSCRIBE_TASK_CREATE_FAILED | 3017 | startSubscribeAudio(), startSubscribeVideo() | Could not create the receiving task. Same cause as 3013: internal RAM. |
STOP_PUBLISH_TASK_CREATE_FAILED | 3018 | leave() | leave() could not start tearing down the sending side, so nothing was torn down and the session is still up. Free memory and call leave() again. See Connection State. |
STOP_SUBSCRIBE_TASK_CREATE_FAILED | 3019 | leave() | Same as 3018, for the receiving side. The session is still up; free memory and call leave() again. See Connection State. |
CANDIDATE_PAIR_FAILED | 3020 | any start*, startMessageChannel() | No working network path was found, usually a network that blocks outbound UDP such as guest Wi-Fi or a captive portal. Try a different Wi-Fi to confirm. |
DTLS_HANDSHAKE_FAILED | 3021 | any start*, startMessageChannel() | The encrypted media (DTLS) handshake failed. Retry. If it repeats, check free internal RAM, and that CONFIG_MBEDTLS_SSL_PROTO_DTLS and CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC are still set in your sdkconfig. |
LEAVE_FAILED | 3022 | leave() | Teardown started but did not finish within 6 seconds. Unlike 3018 and 3019 the session was not left intact, so do not rejoin. Reboot the device. See Connection State. |
INIT_NOT_CALLED | 3023 | every start* and stop*, and the message-channel calls | init() has not run, or it returned an error. Call init() once and check it returned RESULT_OK first. |
DATA_CHANNEL_NOT_STARTED | 3025 | sendMessage(), stopMessageChannel() | The message channel is not open. Call startMessageChannel() once before sending. |
DATA_CHANNEL_QUEUE_FULL | 3026 | sendMessage() | Messages are queuing faster than they can be sent. Retry shortly, and slow your send rate if it recurs. See Send Message. |
Contact VideoSDK support in case of any issues or unknown errors.
Got a Question? Ask us on discord

