Building custom image for single user container with jupyterlab-git gives traitlets.traitlets.TraitError error

I am using jupyterhub for creating a multiuser jupyter notebook server. For the spawning of single-user jupyter notebook sessions, I am using the dockerspawner package. Now, I would like to version control my notebooks, hence, I am trying to use jupyterlab-git extension package. However, I have not been successful so far, so I am here for your advice.

I understand two things to make this extension work (maybe this is where I am wrong?) -

  1. I need to create a custom docker image for single user containers, as none of the images provided by jupyter docker stacks has the jupyterlab-git extension. So, this is my dockerfile for the custom image -
FROM jupyter/minimal-notebook:e407f93c8dcc

ARG JUPYTERHUB_VERSION=3.1.0 # This version should match our jupyterhub deployment 

RUN mamba install --quiet --yes jupyterlab-git==0.41.0 \
    && mamba clean --all -f -y

CMD [""]
  1. The jupyterlab-git version in the single user container should match the jupyterlab-git version in the jupyterhub installation. The following is my requirements.txt for custom jupyterhub image -

However, on trying to start my user server, I get the following error -

jupyterhub  | [W 2023-03-08 23:08:48.499 JupyterHub base:1072] User anmol.bhatia is slow to start (timeout=10)
jupyterhub  | [I 2023-03-08 23:09:07.293 JupyterHub dockerspawner:988] Container 'jupyter-anmol-2ebhatia' is gone
jupyterhub  | [I 2023-03-08 23:09:07.718 JupyterHub dockerspawner:1272] Created container jupyter-anmol-2ebhatia (id: 2614fd0) from image oxaigen/jupyterhub-client:0.1.0
jupyterhub  | [I 2023-03-08 23:09:07.718 JupyterHub dockerspawner:1296] Starting container jupyter-anmol-2ebhatia (id: 2614fd0)
jupyterhub  | [E 2023-03-08 23:09:08.220 JupyterHub user:832] Unhandled error starting anmol.bhatia's server: The 'ip' trait of a Server instance expected a unicode string, not the NoneType None.
jupyterhub  |     Traceback (most recent call last):
jupyterhub  |       File "/usr/local/lib/python3.10/dist-packages/jupyterhub/", line 764, in spawn
jupyterhub  |         server.ip = urlinfo.hostname
jupyterhub  |       File "/usr/local/lib/python3.10/dist-packages/traitlets/", line 715, in __set__
jupyterhub  |         self.set(obj, value)
jupyterhub  |       File "/usr/local/lib/python3.10/dist-packages/traitlets/", line 689, in set
jupyterhub  |         new_value = self._validate(obj, value)
jupyterhub  |       File "/usr/local/lib/python3.10/dist-packages/traitlets/", line 721, in _validate
jupyterhub  |         value = self.validate(obj, value)
jupyterhub  |       File "/usr/local/lib/python3.10/dist-packages/traitlets/", line 2400, in validate
jupyterhub  |         self.error(obj, value)
jupyterhub  |       File "/usr/local/lib/python3.10/dist-packages/traitlets/", line 827, in error
jupyterhub  |         raise TraitError(e)
jupyterhub  |     traitlets.traitlets.TraitError: The 'ip' trait of a Server instance expected a unicode string, not the NoneType None.
jupyterhub  |
jupyterhub  | [I 2023-03-08 23:09:08.225 JupyterHub dockerspawner:988] Container 'jupyter-anmol-2ebhatia' is gone
jupyterhub  | [W 2023-03-08 23:09:08.225 JupyterHub dockerspawner:963] Container not found: jupyter-anmol-2ebhatia
jupyterhub  | [E 2023-03-08 23:09:08.628 JupyterHub gen:630] Exception in Future <Task finished name='Task-44' coro=<BaseHandler.spawn_single_user.<locals>.finish_user_spawn() done, defined at /usr/local/lib/python3.10/dist-packages/jupyterhub/handlers/> exception=TraitError("The 'ip' trait of a Server instance expected a unicode string, not the NoneType None.")> after timeout

Here is the relevant part from my file -

c = get_config()

def create_dir_hook(spawner):
    """Create directory"""
    username =  # get the username
    volume_path = os.path.join('/volumes/jupyterhub', username)
    if not os.path.exists(volume_path):
        os.mkdir(volume_path, 0o755)
        # now do whatever you think your user needs
        # ...

def clean_dir_hook(spawner):
    """Delete directory"""
    username =  # get the username
    temp_path = os.path.join('/volumes/jupyterhub', username, 'temp')
    if os.path.exists(temp_path) and os.path.isdir(temp_path):

# attach the hook functions to the spawner
# pylint: disable=undefined-variable
c.Spawner.pre_spawn_hook = create_dir_hook
c.Spawner.post_stop_hook = clean_dir_hook

# spawn with Docker
c.JupyterHub.spawner_class = "dockerspawner.DockerSpawner"
c.DockerSpawner.image = "oxaigen/jupyterhub-client:0.1.0"
c.DockerSpawner.network_name = "jupyterhub-network"
c.DockerSpawner.use_internal_ip = True
c.DockerSpawner.notebook_dir = "/home/jovyan/work"
c.DockerSpawner.volumes = {'/volumes/jupyterhub/{username}/': '/home/jovyan/work'}
c.DockerSpawner.remove = True
c.DockerSpawner.debug = True
c.DockerSpawner.start_timeout = 60 * 5

# Hub IP
c.JupyterHub.hub_ip = ""

If someone has faced any similar issue, please let me know how you debugged the issue.
Any general tip/advice is also appreciated. TIA