SSLError: wrong version number

Hi, My name is Andrew and I’m currently working on integrating shotgun to our automation tools. Everything is running nicely until recently we encountered a rather peculiar problem as the console shown below whenever we try to query a task from shotgun server (using shotgun.find method).

ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:2622)

The problem seems to occur randomly. Sometimes the code will run fine and the query shows up but on the next or other occasion the error will pop-up then crashed the entire code.

We’ve been looking everywhere and sounds its a problem with mismatched openssl version between the client and the server. However, we’ve got no definitive solution to fix the problem. Perhaps if anyone has ever encountered such kind of error or has any idea on why it happens randomly can share their solution. Thank you.

1 Like

It is not entirely clear how your setup is organized, and in what context it runs.
Where is openssl coming from? There was the TLS version switch a while ago in Shotgun, there must be a document describing how to upgrade your system.

1 Like

Hi mmoshev, thank you for your reply. My setup is using shotgun python API and the error occurred during find or find_one method of the API. At the moment I will try to see about the TLS version switch you have mentioned. Thank you for your input. Cheers.

Which python version do you use? Is it a normal installation?

Here is the article: Insecure HTTPS and Old Toolkit Core Deprecation - May 15th, 2019 – Shotgun Support

You need certain versions of programs to support this.

Hi mmoshev, thank you for the article. I’m reading it at the moment.

We are currently using python 3.8.5 (32 bit) and it is a normal installation from python.org.

At the moment (due to studio tight schedule and the high importance for the code within the pipeline), I’ve disabled the SSL validation using:

shotgun_api3.shotgun. NO_SSL_VALIDATION = True

We felt that this is only a temporary solution. Therefore, we will look over the article you’ve provided and find more permanent solution. Thank you so much for your help so far.

Oh okay, if you are using such a new python it would be a different cause, then.

A quick search on Stack Overflow suggests either

  • you are not passing the https:// protocol part in the url
  • you are using a wrong port
  • proxy is terminating ssl
  • certificates are not properly set up

I suppose you are using latest versions of sg api & toolkit?

1 Like

We too started getting this exact issue today.
We previously were using a python 2 version of the API that I had ported to python 3.0. This has been working fine for several years.

Yesterday we upgraded to shotgrid api 3.3.1
We are running python 3.7.7

Randomly (Not always) we are getting:
[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:2555)

during a find_one method of the API.

Something to note is the API is being ran by 12 threads, the first find_one call in each thread failed with this error, then all calls to find_one after first failure in each thread were successful. Seems like this might be related.

The error definitely is threading related.

Here is example code

import shotgun_api3
import threading

sgScriptName = <scriptname>
sgApiKey = <scriptkey>
sgProjectName = <projectname>

num_threads = 5

sg = shotgun_api3.Shotgun(<URL>, script_name=sgScriptName, api_key=sgApiKey)
sgProject = sg.find_one("Project", [["name", "is", sgProjectName]])

def worker():
    for i in range(5):
        try:
            category = sg.find_one('Episode', [['code','is', 'F_FaceOnly']], ['code'])
            print(i, category)
        except Exception as exc:
            print("Exception thrown during SGX worker thread: %s", exc)

threads = [ threading.Thread(target=worker) for _i in range(num_threads) ]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

print("All Done")

after a little google searching it appears that httplib2 is not thread safe, you need a httplib2.Http() per thread.

We can create a Shotgun client per thread and get around this.

2 Likes

Do you have a sample of how you created a connection per thread to solve this problem. I’m experiencing the same issue here. Quite confusing and unfortunate that it is not thread safe. I’d be curious to see how you did it.

I’ve usually implemented this with something like the clone method below, manually cloning the ShotgunClient wrapper for thread calls.

You could perhaps find an automated way to do something similar, but doing it manually keeps me honest, so for me that seems like the best way.

As for implementing actual thread-safe http calls, that would take some heavier lifting.

import shotgun_api3


class ShotgunConfig:
    '''Shotgun site config goes here'''

    host = '<your site here>'
    clientId = 'script/client id'
    clientSecret = 'script/client secret'


class ShotgunClient:

    def __init__(self, sessionToken: str=None) -> None:
        '''Shotgun API wrapper for all your stuffs

        To access the `shotgun_api3` instance directly at any stage, use the `instance` getter
        '''

        # Use existing session token
        if sessionToken:
            self._instance = shotgun_api3.Shotgun(
                base_url = ShotgunConfig.host, 
                connect = False, 
                session_token = sessionToken
            )
            self._instance._connection = None

        # Brand new connection
        else:
            self._instance = shotgun_api3.Shotgun(
                base_url = ShotgunConfig.host, 
                script_name = ShotgunConfig.clientId, 
                api_key = ShotgunConfig.clientSecret
            )

    @property
    def instance(self) -> shotgun_api3.Shotgun:
        '''Returns the current `shotgun_api3.Shotgun` instance'''

        return self._instance

    def clone(self):
        '''Clone current instance and return a pre-authenticated new copy'''

        return ShotgunClient(sessionToken=self.instance.config.session_token)

    # Other awesome methods below
    ...

This is very interesting thank you for sharing.
How would you use this class in practice then? Just for more context on your use of it.

I may dig around in their docs to see how they achieve this with the toolkit threading.

Hey @JokerMartini,

Sorry I forgot about this post for a few days. Reading some comments from the other thread that deals with more or less this same problem inspired me find a better solution than the one I currently had implemented. Here’s a reproducible demo singleton file for you to check out:

I believe the demo code from above answer your question as to how I normally use the ShotgunClient wrapper, but in case it’s not very clear: There’s a lot of repeated code across a given project for stuff like “get all shots in a project”, which usually leads me to create a place to collect these common calls. This “place” is also a handy storage location for other related things like connection instances, session ids, etc.

Usually this blows out into it’s own shotgun wrapper module for me, which generally contains a class like the ShotgunClient wrapper along with misc helper methods that’s required for generating and extracting entities and other useful things.

Run the code from the gist above, see how it feels, and let me know if you have any more questions. There’s probably an infinite number of ways to solve this design-challenge, this is just my (current) preference.