JupyterHub: server spawn fails (500 / spawner_image not found)¶
Symptom¶
After logging in at code.<scs>.<domain>, starting a notebook shows:
- 500 Internal Server Error
- Unhandled error starting server <username>
Hub logs (docker compose logs jupyterhub--jupyterhub--app) contain:
pull access denied for spawner_image, repository does not exist or may require 'docker login'
or docker.errors.ImageNotFound for fromImage=spawner_image.
Cause¶
JupyterHub spawns user containers from a local-only Docker image named spawner_image (see DOCKER_JUPYTER_IMAGE in jupyterhub/docker-compose.yml). That image is built by the jupyterhub--spawner--builder compose service; it is not pulled from a registry and is not started automatically (deploy.replicas: 0).
If the image was never built, or was removed during docker image prune, spawn fails with HTTP 500.
Fix¶
From the deployment root (with COMPOSE_FILE from .env):
docker compose build jupyterhub--spawner--builder
Verify:
docker images spawner_image
Then retry starting the server from the Hub home page (no Hub restart required).
When to rebuild¶
Rebuild after changes under jupyterhub/spawner_image/ (Dockerfile, Nextcloud sync extension, server extension package):
docker compose build jupyterhub--spawner--builder
Existing user containers keep running until stopped; new spawns use the updated image.
Build notes¶
- The spawner Dockerfile uses a Python 3.12 build stage (
nikolaik/python-nodejs:python3.12-nodejs22) to compile the JupyterLab extension; Python 3.14 does not yet ship compatible JupyterLab wheels. - Labextension bundling calls
/tmp/jlbuild/bin/jupyter-builder builddirectly (the deprecatedjupyter labextension buildwrapper looks upjupyter-builderonPATH, which fails inside an isolated venv).
Related¶
- OpenRefine must exist at
JUPYTERHUB_OPENREFINE_DIR(default:$PWD/openrefinein root.env). Run01_scripts/jupyterhub/pre-install.shif missing. - Hub logs:
docker compose logs -f jupyterhub--jupyterhub--app