Unclear 2003 error

Connection via Android Zoom with a generated JWT fails with 2003 errors.
I understand something in jwt data and connection to session might not be matching, or invalid, but plain 2003 does not help understand what exactly.

Which Android Video SDK version?

To Reproduce(If applicable)
Steps to reproduce the behavior:

  1. Generate a JWT token with server:

“iat”: 1651186584,
“exp”: 1651204584,
“app_key”: “****”,
“version”: 1,
“role_type”: 1,
“user_identity”: “a persons name”,
“session_key”: “62f6f230c14c49308069510fe280eb8c”,
“tpc”: “1182249090cb4e29a8ece25e2c46255c”

  1. Click on ‘…’

val params = ZoomVideoSDKSessionContext().apply {
sessionName = sessionId
sessionPassword = sessionSecret
userName = personName
token = jwt
audioOption = audioOptions
videoOption = videoOptions

onSessionJoin sessionName=1182249090cb4e29a8dce25e2c46255c userName=Florian sessionPassword=null

  1. See error 2003 and dont know why.
    Is the tpc too long ? everything is alphanumeric

If applicable, add screenshots to help explain your problem.

Smartphone (please complete the following information):

  • Device: [e.g. Pixel 5]
  • OS: [e.g. Android 11]

Additional context
Add any other context about the problem here.

Who wants some stackoverflow points, also happy to be answered here: Troubles creating a Zoom Meeting SDK session on android with generated JWT token, always leads to 2003 error - Stack Overflow

Hi @florian, thanks for using our SDK.

I’m not seeing anything immediately wrong with how you’re trying to join the session. Can you also provide a snippet showing how you are initializing the SDK so we can confirm there’s nothing going on there?


Thank you for your response, I gather the most important parts:

fun globalInit(context: Context) {

        val params = ZoomVideoSDKInitParams().apply {
            domain = "https://zoom.us" // Required
            logFilePrefix = "BOX" // Optional for debugging
            enableLog = true // Optional for debugging
        sdk = ZoomVideoSDK.getInstance()
        if (!initialized) {
            val initResult = sdk.initialize(context, params)
            if (initResult == Errors_Success) {
                Timber.i("sdk.initialize OK")
                initialized = true
            } else {
                Timber.e("sdk.initialize failed: $initResult")
 fun joinSession(sessionId: String, personName: String, jwt: String) {
        // Setup audio options
        val audioOptions = ZoomVideoSDKAudioOption().apply {
            connect = true
            mute = false
        // Setup video options
        val videoOptions = ZoomVideoSDKVideoOption().apply {
            localVideoOn = true // Turn on local/self video upon joining
        val parses = jwt.split(":")
        var sessionName = sessionId
        var userName = personName
        var token = jwt
        if (parses.isNotEmpty() && parses.size >3) {
            sessionName = parses[1]
            userName = parses[2]
            token = parses.last()
        val params = ZoomVideoSDKSessionContext().apply {
            this.sessionName = sessionName
            this.userName = userName
            this.token = token
//            audioOption = audioOptions
//            videoOption = videoOptions
        Timber.i("onSessionJoin sessionName=$sessionName userName=$userName token=$token")


As you can see our server sends the token encapsulated like:


I/ZoomWrapper: onSessionJoin sessionName=1651514846382 userName=username token=…jwtToken…

Addendum: of course the jwt is different then from first post, as I tried with shorter values, for example just a timestamp for tpc, but still not working:

“app_key”: “appkey”,
“version”: 1,
“role_type”: 1,
“iat”: 1651514846382,
“exp”: 1651543646382,
“tpc”: “1651514846382”


Hi @florian,

Thanks for the additional information. I’m seeing one discrepancy, which is the format of the timestamps. It looks like in the first post you are providing them as seconds, but in the latest reply they’re milliseconds. Just to be clear, these timestamps should be in seconds.

Assuming you are seeing the same error regardless of the timestamps, I’m not seeing any issues with your implementation. Can you please provide the encrypted SDK logs so we can investigate further? In case you aren’t aware, instructions on how to get the SDK logs can be found here (that’s for the Meeting SDK, but the location of logs will be the same in the Video SDK).


thank you, where should I send the logs to ?

Here I cannot upload “txt” files, please send me an email in a private message, I cannot message you here or via linkedIn…

I tried using seconds instead of milliseconds, but just 2003. Is there a way to get more fine granulated error codes ?

Hi @florian,

You can either upload the logs to a file sharing service or submit them through a ticket on our developer support site. If you choose the latter option, please let me know the ticket number so that I can locate the logs.


Thank your for that patient explanation!
We created a Support issue:

That was the safes way, did not want to put that on a sharing service and forget about it :wink:
Thank you, I hope there are some insights! On the flutter app it worked somehow, 2 weeks ago, with other demo credentials.

Is there a way to get more debug logs locally?
In the mean time: thank you for your time and patient support,


Hi @florian,

Thanks for providing that. Confirming that we have received your logs and are investigating this error. I’ll keep you updated once we have any additional information.

Is there a way to get more debug logs locally?

Unfortunately the error code produced by the SDK is about as in-depth as we can get. The encrypted SDK logs do have more information, but they can only be decrypted by Zoom due to the nature of the information included in them.


Hi @florian,

Actually upon taking another look at your implementation, I wanted to confirm something. It looks like you’re splitting the JWT and only providing the last segment of it as the token param. This means that you are not sending the whole JWT, only the signature of it. So in the example value you provided, it would be sending TQa0L6G3_svpZ3aSNw2A-BHz3POYpsn4m5Tzjd6-Wd0, which is incorrect. The entire JWT should be set as the token param. Can you confirm whether this is the approach you are using?


No, my JWT should be alright:

“app_key”: “app_key”,
“version”: 1,
“role_type”: 1,
“iat”: 1652156419,
“exp”: 1652178019,
“tpc”: “1652156419”

“app_key” and “secret” are of course my zoom secrets.

In Json payload we just send the token encapsulated and together with tpc and “user_identity”, as we thought we give it a try, if user_identity a) has certain requirements b) must match on joining c) is not optional but mandatory.

	"id": "556b57f2-d29c-4813-9dbb-300a3d6d3ea4",
	"senderId": "c9efca37-bf8f-4d92-8dc9-a9df6ea5e53c",
	"receiverId": "043d6980-3273-4788-9591-3475631c6f92",
	"callType": "VIDEO",
	"startedAt": null,
	"finishedAt": null,
	"callState": "CALLING",
	"token": "zoom:1652156419:reprehenderit:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBfa2V5IjoiYXBwX2tleSIsInZlcnNpb24iOjEsInJvbGVfdHlwZSI6MSwiaWF0IjoxNjUyMTU2NDE5LCJleHAiOjE2NTIxNzgwMTksInRwYyI6IjE2NTIxNTY0MTkifQ.rQrW__LMDhoIqN8pLLMdesmHWgZIX9tw8Ywy1Guhq6g",
	"createdAt": "2022-05-09T22:20:19.591917+02:00",
	"sentAt": "2022-05-09T22:20:19.715638+02:00",
	"retrievedAt": null

I dont know anymore, as we need it pretty soon; we might switch back to Jitsi I guess ?
We need a SDK to be predictable and debuggable…

The secret is given base64 encoded, yes ?

Screenshot from 2022-05-09 22-31-26

Hi @florian,

In my previous message, I was referring to this line in your implementation:

val parses = jwt.split(":")

Here you are splitting the JWT into 3 individual strings for the header, payload, and signature. Then later in your implementation, you are passing in the signature. Instead of doing this, please try providing the jwt value as a whole. Your payload seems correct, so I think that this is likely the cause of the error you are seeing. If not, we can certainly investigate further.


No I did not split the JWT… I encasulated it like this: “username:session:JWT”, the JWT itself has of course its original header, payload and signature.

Be aware that I split on “:”, not “.”

In the end we ended up using Jitsi for the Open version and Twilio for the commercial, we just need to have a debuggable system and rely on java docs. Even if your support was nice, we cannot build on that alone, the logs were just missing…

Thank you personally for your time Jon!

@ Florian

Have you fix this error? I also got this error too.

(No, it was too hard to fix., we had to pivot)

Be aware that “2003” could mean many things:

  • look at your timestamps, must be seconds
  • ensure you meet the string length requirements for user_identity, session_key and tpc
  • connecting user’s name should match user_identity, I guess

Thank you ! I fixed my issue on yesterday. I set timestamps to second and it’s worked