After upgrade to JupyterHub 2.0.0: 404 : Not Found You are requesting a page that does not exist!

I hate this so much, I want to vomit blood right now.

So, I have a docker with Ubuntu 20.04 image, where I have jupyterhub installed. So far, I had apparently had jupyterhub 1.5.0; and I had always started it in the image directly from the command line with:

jupyterhub -f /etc/jupyterhub/

… where in I’ve only had c.Spawner.notebook_dir = '/home/mydir', which still exists as folder. And everything used to work fine.

So, I manage the jupyterhub and jupyter installation via pip-compile and pip-sync, and today I updated that - and jupyterhub got updated to 2.0.0; and I started getting these problems. I even generated a new config file (and added the above line) - still nothing.

First I experienced this:

# jupyterhub -f /etc/jupyterhub/
[I 2021-12-19 12:36:46.886 JupyterHub app:2717] Running JupyterHub version 2.0.0
[I 2021-12-19 12:36:46.887 JupyterHub app:2747] Using Authenticator: jupyterhub.auth.PAMAuthenticator-2.0.0
[I 2021-12-19 12:36:46.887 JupyterHub app:2747] Using Spawner: jupyterhub.spawner.LocalProcessSpawner-2.0.0
[I 2021-12-19 12:36:46.887 JupyterHub app:2747] Using Proxy: jupyterhub.proxy.ConfigurableHTTPProxy-2.0.0
[I 2021-12-19 12:36:46.890 JupyterHub app:1596] Loading cookie_secret from /jupyterhub_cookie_secret
Found database schema version 4dc2d5a8c53c != 833da8570507. Backup your database and run `jupyterhub upgrade-db` to upgrade to the latest schema.

… and i tried jupyterhub upgrade-db - but ultimately, that doesn’t matter, because the .sqlite file apparently gets created in the directory where you run jupyterhub from; so in the end I deleted the .sqlite file, and it got recreated on next run.

The big problem is, that once I open; I get asked to log in - I log in with the user I made for this purpose (juser), and once the progressbar is shown, ultimately I get this, instead of the list of files in the start folder:

404 : Not Found

You are requesting a page that does not exist!

And the JupyterHub log in terminal says only:

[I 2021-12-19 13:24:43.901 SingleUserNotebookApp log:189] 302 GET /user/juser/tree/? -> /user/juser/tree? (@::ffff: 0.48ms
[W 2021-12-19 13:24:43.986 SingleUserNotebookApp log:189] 404 GET /user/juser/tree? (@::ffff: 20.79ms

… AAAAH!!! WHICH is this page I’m requesting, that does not exist? /user/juser/tree/? is not a file path anyways …

How do I debug this (i.e., how do I find what resource is jupyterhub looking for, that it cannot find), and how do I get jupyterhub to start working again?

At least, I can confirm this still works in my image (note, ip must be, else the server is not accessible outside of the docker image):

# jupyter notebook --port 8000 --ip --allow-root --no-browser

Anyways, in hopes of finding what generates this error, I tried to trace:

# # python3 -m trace  --ignore-dir=/usr/lib/ -t `which jupyterhub` -f /etc/jupyterhub/ > /path/to/jhub.log 2>&1

… and reproduced the error - and got somewhere here:

 --- modulename: iostream, funcname: closed         return self._closed             if (         return True                 if not ret:                 await asyncio.sleep(0)
 --- modulename: web, funcname: <lambda>         fut.add_done_callback(lambda f: f.result())
 --- modulename: http1connection, funcname: _server_request_loop                 conn = HTTP1Connection(, False, self.params, self.context)
 --- modulename: http1connection, funcname: __init__         self.is_client = is_client
 --- modulename: httpserver, funcname: start_request         if isinstance(self.request_callback, httputil.HTTPServerConnectionDelegate):             delegate = self.request_callback.start_request(server_conn, request_conn)
 --- modulename: routing, funcname: start_request         return _RoutingDelegate(self, server_conn, request_conn)
 --- modulename: routing, funcname: __init__         self.server_conn = server_conn         self.request_conn = request_conn         self.delegate = None  # type: Optional[httputil.HTTPMessageDelegate]         self.router = router  # type: Router
 --- modulename: iostream, funcname: _maybe_add_error_listener         if self._state is None or self._state == ioloop.IOLoop.ERROR:                 not self.closed()
 --- modulename: iostream, funcname: closed         return self._closed             if (                 except (                     iostream.StreamClosedError,                     iostream.UnsatisfiableReadError,                     asyncio.CancelledError,
[I 2021-12-19 16:28:18.338 SingleUserNotebookApp log:189] 302 GET /user/juser/ -> /user/juser/tree/? (@::ffff: 1.65ms
[I 2021-12-19 16:28:18.364 SingleUserNotebookApp log:189] 302 GET /user/juser/tree/? -> /user/juser/tree? (@::ffff: 0.88ms
[W 2021-12-19 16:28:18.415 SingleUserNotebookApp log:189] 404 GET /user/juser/tree? (@::ffff: 34.09ms                 except (                     return             delegate.on_close(self)
 --- modulename: httpserver, funcname: on_close         self._connections.remove(typing.cast(HTTP1ServerConnection, server_conn))                     return
 --- modulename: ioloop, funcname: <lambda>                 lambda f: self._run_callback(functools.partial(callback, future))
 --- modulename: ioloop, funcname: _run_callback

Well, I still can’t really see where do these printouts come from … What a goddamn waste of time …

I’d recommend reading this post on how to get answers to your questions. I understand you are frustrated, but it is not productive to vent to this degree if you want help.

Since the change happened with an environment update, it’s good to include the output of pip freeze. Since it is in a Docker image, if you can include your Dockerfile (or if the image is public, a link to the image repository itself), that would be helpful to share, if you can. Including more of the log output (especially the output during startup) is helpful, too.

My guess is that jupyterhub was updated, but perhaps jupyter_server and/or jupyterlab are out-of-date. If you want to stick with the classic notebook server, you can set the environment variable:

export JUPYTERHUB_SINGLEUSER_APP='notebook.notebookapp.NotebookApp'

I agree with minRK.

We all like a world that is predictable and where everything just works, but emotionally charging posts does no-one a benefit. Forgive me for being direct, but it makes readers think you’re a bit of a diva.

I recommend that you follow minRKs advice and then come back and edit your post to make it problem oriented instead of what it is now.

Then it’ll give it a +1 .

With all the best intentions,