Skip to main content
Version: 2.x.x

Error Handling - React Native

Actions such as join(), unmuteMic() or pin() return a Promise. The Promise rejects when the SDK refuses the action or the action fails. Errors that happen on their own, such as a rejected token or a lost connection, arrive on the onError callback of useRoom(). This page shows how to handle both.

Every error code is listed in Error Events.

Catch rejected actions​

Await each action inside try / catch. A rejection that you do not catch never reaches your code. React Native only logs a "Possible unhandled promise rejection" warning.

import { Button } from "react-native";
import { useRoom } from "@videosdk.live/react-native-sdk";

function UnmuteButton() {
const { unmuteMic } = useRoom();

const onPress = async () => {
try {
await unmuteMic();
} catch (error) {
console.warn("Could not unmute:", error.code, error.name, error.message);
}
};

return <Button title="Unmute" onPress={onPress} />;
}

Where you cannot use await, add a .catch() handler to the call:

import { Button } from "react-native";
import { useRoom } from "@videosdk.live/react-native-sdk";

function LeaveButton() {
const { leave } = useRoom();

return (
<Button
title="Leave"
onPress={() => leave().catch((error) => console.warn("Leave failed:", error.code))}
/>
);
}

createCameraVideoTrack(), createMicrophoneAudioTrack() and createScreenShareVideoTrack() reject the same way, so catch the error where you call them.

Read the error​

The rejected value is an Error with three properties:

  • code: The error code, a number such as 3055.
  • name: The name of the error, such as "ERROR_OPERATION_IN_PROGRESS". For a code that Constants.VideoSDKError does not list, name is "Error".
  • message: A description. Log it, but check code in your code, not message.

Constants.VideoSDKError maps each error name to its code, so you can compare codes without writing numbers. The example below also disables the button while the call runs, so a second tap cannot cause 3055:

import { useState } from "react";
import { Button } from "react-native";
import { Constants, useRoom } from "@videosdk.live/react-native-sdk";

const { VideoSDKError } = Constants;

function CameraButton() {
const { enableCam } = useRoom();
const [busy, setBusy] = useState(false);

const turnOnCamera = async () => {
setBusy(true);
try {
await enableCam();
} catch (error) {
switch (error.code) {
case VideoSDKError.ERROR_ALREADY_IN_REQUESTED_STATE:
break; // the camera is already on
case VideoSDKError.ERROR_ROOM_RECONNECTING:
console.warn("Reconnecting. Try again in a moment.");
break;
case VideoSDKError.ERROR_CAMERA_ACCESS_DENIED_OR_DISMISSED:
console.warn("Allow camera access in Settings.");
break;
default:
console.warn("Could not turn on the camera:", error.code, error.message);
}
} finally {
setBusy(false);
}
};

return <Button title="Turn on camera" disabled={busy} onPress={turnOnCamera} />;
}

An unexpected failure inside the SDK rejects with code set to the string "ERROR_BRIDGE_UNEXPECTED" and name set to "Error". Log its message and report it to VideoSDK support.

Common codes​

CodeNameWhenWhat to do
3035ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINEDThe room has not joined yet, or it has left.Call actions from onRoomJoined or later.
3054ERROR_ALREADY_IN_REQUESTED_STATEThere is nothing to do, for example unmuteMic() while the mic is on.You can usually ignore it.
3055ERROR_OPERATION_IN_PROGRESSThe same action is still running, for example after a double tap.Disable the control until the first call settles.
3065ERROR_ROOM_RECONNECTINGThe room is reconnecting.Try again after onRoomStateChanged reports "CONNECTED".
3073ERROR_INVALID_PARAMETERAn argument has the wrong type, a required argument is missing, or an argument names something that does not exist, such as a video processor that was never registered.Fix the argument.
3079ERROR_OPERATION_TIMED_OUTThe request got no answer in time.Check the connection and try again.

Many actions also have codes of their own, for example 3017 (ERROR_CAMERA_ACCESS_DENIED_OR_DISMISSED) when the app has no camera access.

Errors on onError​

onError receives { code, name, message }. It reports errors that happen on their own, such as a rejected token, a lost connection or a camera that stops during the call, and some failed actions. Pass it to useRoom():

import { Constants, useRoom } from "@videosdk.live/react-native-sdk";

function RoomErrors() {
useRoom({
onError: ({ code, name, message }) => {
if (code === Constants.VideoSDKError.ERROR_ROOM_RECONNECTING) return; // wait for onRoomStateChanged
console.warn("Room error:", code, name, message);
},
});

return null;
}

Errors that reach both​

Some failures reject the call and are also reported on onError. Handle each code in one place, for example by leaving the codes that your catch blocks handle out of onError.

  • An action of useRoom() called before join(), or after the room has left, rejects with 3035 and also reports it on onError.
  • An action called after join() but before onRoomJoined, or while the room is reconnecting, behaves differently on each platform. On Android, most actions report 3035 or 3065 on onError and resolve without doing anything. On iOS, most actions reject with the same codes and do not call onError. Handle both codes in onError and in catch.
  • On iOS, a camera or microphone that cannot be opened after enableCam() or unmuteMic() is reported only on onError, and the call resolves. On Android, it is reported on onError and the call also rejects.

Other errors​

  • setSharedKey() of BaseKeyProvider does not return a Promise. It throws 3073 (ERROR_INVALID_PARAMETER) at once for an empty key, so call it inside try / catch.
  • runPreCallTest() rejects with a PreCallTestError, whose code is a string. See Pre-call errors.

API Reference​

The API references for all the methods and events utilized in this guide are provided below.

Got a Question? Ask us on discord