Repository: jupyterhub/jupyterhub

Issue:
Too many redirects when trying to access my server
I successfully installed and logged in to the Jupyter Hub as an admin (using Python 3.4), but when I try and access 'My Server' I get a 'too many redirects' error in the browser. Every time I try and access it, the log output is:

```
[I 19:11:02.041 tornado.access] 302 GET /hub/user/tom/ (::1) 10.50ms
[I 19:11:02.075 tornado.access] 302 GET /user/tom/ (::1) 0.46ms
[I 19:11:02.086 tornado.access] 302 GET /hub/user/tom/ (::1) 8.38ms
[I 19:11:02.089 tornado.access] 302 GET /user/tom/ (::1) 0.34ms
[I 19:11:02.099 tornado.access] 302 GET /hub/user/tom/ (::1) 8.10ms
[I 19:11:02.101 tornado.access] 302 GET /user/tom/ (::1) 0.33ms
[I 19:11:02.113 tornado.access] 302 GET /hub/user/tom/ (::1) 8.10ms
[I 19:11:02.116 tornado.access] 302 GET /user/tom/ (::1) 0.33ms
[I 19:11:02.127 tornado.access] 302 GET /hub/user/tom/ (::1) 9.07ms
[I 19:11:02.130 tornado.access] 302 GET /user/tom/ (::1) 0.48ms
[I 19:11:02.140 tornado.access] 302 GET /hub/user/tom/ (::1) 7.72ms
[I 19:11:02.142 tornado.access] 302 GET /user/tom/ (::1) 0.31ms
[I 19:11:02.152 tornado.access] 302 GET /hub/user/tom/ (::1) 8.02ms
[I 19:11:02.155 tornado.access] 302 GET /user/tom/ (::1) 0.34ms
[I 19:11:02.164 tornado.access] 302 GET /hub/user/tom/ (::1) 8.03ms
[I 19:11:02.168 tornado.access] 302 GET /user/tom/ (::1) 0.67ms
[I 19:11:02.178 tornado.access] 302 GET /hub/user/tom/ (::1) 8.21ms
```



Discussion:
Can you include any other log statements about starting or stopping the single-user server? I suspect something is going wrong with bringing that server down prematurely.

@minrk - here's the full log of what happens when I start up `jupyterhub` and then click on `My Server`:

```
$ jupyterhub
[I 19:15:49.827 JupyterHubApp] Not using whitelist. Any authenticated user will be allowed.
[I 19:15:49.838 JupyterHubApp] Starting proxy: ['configurable-http-proxy', '--ip', '', '--port', '8000', '--api-ip', 'localhost', '--api-port', '8001', '--default-target', 'http://localhost:8081']
19:15:49.931 - info: [ConfigProxy] Proxying http://*:8000 to http://localhost:8081
19:15:49.933 - info: [ConfigProxy] Proxy API at http://localhost:8001/api/routes
[I 19:15:59.123 tornado.access] 302 GET / (::1) 0.88ms
[I 19:15:59.131 tornado.access] 302 GET /hub/ (::1) 5.21ms
[E 19:15:59.157 tornado.general] Could not open static file '/Users/tom/Library/Python/3.4/share/jupyter/static/images/favicon.ico'
[I 19:15:59.159 tornado.access] 200 GET /hub/home (::1) 25.05ms
[I 19:15:59.260 tornado.access] 304 GET /hub/static/js/home.js (::1) 9.03ms
[I 19:15:59.273 tornado.access] 304 GET /hub/static/js/jhapi.js (::1) 0.73ms
[I 19:15:59.276 tornado.access] 304 GET /hub/static/js/utils.js (::1) 0.60ms
[I 19:15:59.311 tornado.access] 302 GET / (::1) 0.40ms
[I 19:15:59.318 tornado.access] 302 GET /hub/ (::1) 3.17ms
[I 19:15:59.362 tornado.access] 304 GET /hub/home (::1) 6.25ms
[I 19:16:01.206 JupyterHubApp] Spawning ['jupyterhub-singleuser', '--user=tom', '--port=55653', '--cookie-name=jupyter-hub-token-tom', '--base-url=/user/tom', '--hub-prefix=/hub/', '--hub-api-url=http://localhost:8081/hub/api']
2014-10-03 19:16:01.756 [SingleUserNotebookApp] Using existing profile dir: '/Users/tom/.ipython/profile_default'
2014-10-03 19:16:01.780 [SingleUserNotebookApp] Using MathJax from CDN: https://cdn.mathjax.org/mathjax/latest/MathJax.js
2014-10-03 19:16:01.796 [SingleUserNotebookApp] Serving notebooks from local directory: /Users/tom
2014-10-03 19:16:01.796 [SingleUserNotebookApp] 0 active kernels 
2014-10-03 19:16:01.796 [SingleUserNotebookApp] The IPython Notebook is running at: http://localhost:55653/user/tom/
2014-10-03 19:16:01.796 [SingleUserNotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[I 19:16:01.832 JupyterHubApp] Adding user tom to proxy /user/tom => http://localhost:55653
[I 19:16:01.856 tornado.access] 302 GET /hub/user/tom/ (::1) 672.53ms
[I 19:16:01.858 tornado.access] 302 GET /user/tom/ (::1) 0.38ms
[I 19:16:01.868 tornado.access] 302 GET /hub/user/tom/ (::1) 8.19ms
[I 19:16:01.871 tornado.access] 302 GET /user/tom/ (::1) 0.34ms
[I 19:16:01.880 tornado.access] 302 GET /hub/user/tom/ (::1) 7.44ms
[I 19:16:01.883 tornado.access] 302 GET /user/tom/ (::1) 0.37ms
[I 19:16:01.893 tornado.access] 302 GET /hub/user/tom/ (::1) 8.17ms
[I 19:16:01.896 tornado.access] 302 GET /user/tom/ (::1) 0.32ms
[I 19:16:01.906 tornado.access] 302 GET /hub/user/tom/ (::1) 8.45ms
[I 19:16:01.909 tornado.access] 302 GET /user/tom/ (::1) 0.35ms
[I 19:16:01.918 tornado.access] 302 GET /hub/user/tom/ (::1) 7.93ms
[I 19:16:01.921 tornado.access] 302 GET /user/tom/ (::1) 0.35ms
[I 19:16:01.931 tornado.access] 302 GET /hub/user/tom/ (::1) 8.16ms
[I 19:16:01.933 tornado.access] 302 GET /user/tom/ (::1) 0.31ms
[I 19:16:01.945 tornado.access] 302 GET /hub/user/tom/ (::1) 9.62ms
[I 19:16:01.949 tornado.access] 302 GET /user/tom/ (::1) 0.52ms
[I 19:16:01.959 tornado.access] 302 GET /hub/user/tom/ (::1) 8.27ms
```

Can you run again with `--debug`?

@minrk - here goes:

```
$ jupyterhub --debug
--- Logging error ---
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 971, in emit
    msg = self.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 821, in format
    return fmt.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 121, in format
    return super(LevelFormatter, self).format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 561, in format
    s = self.formatMessage(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 530, in formatMessage
    return self._style.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 374, in format
    return self._fmt % record.__dict__
KeyError: 'color'
Call stack:
  File "/Users/tom/Library/Python/3.4/bin/jupyterhub", line 4, in <module>
    main()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 563, in launch_instance
    app.initialize(argv)
  File "<string>", line 2, in initialize
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/Users/tom/Library/Python/3.4/lib/python/site-packages/jupyterhub/app.py", line 587, in initialize
    super(JupyterHubApp, self).initialize(*args, **kwargs)
  File "<string>", line 2, in initialize
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 256, in initialize
    self.parse_command_line(argv)
  File "<string>", line 2, in parse_command_line
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 499, in parse_command_line
    self.update_config(config)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 398, in update_config
    self.config = newconfig
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/utils/traitlets.py", line 371, in __set__
    obj._notify_trait(self.name, old_value, new_value)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/utils/traitlets.py", line 520, in _notify_trait
    c(name, old_value, new_value)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 247, in _config_changed
    self.log.debug('Config changed:')
Message: 'Config changed:'
Arguments: ()
--- Logging error ---
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 971, in emit
    msg = self.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 821, in format
    return fmt.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 121, in format
    return super(LevelFormatter, self).format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 561, in format
    s = self.formatMessage(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 530, in formatMessage
    return self._style.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 374, in format
    return self._fmt % record.__dict__
KeyError: 'color'
Call stack:
  File "/Users/tom/Library/Python/3.4/bin/jupyterhub", line 4, in <module>
    main()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 563, in launch_instance
    app.initialize(argv)
  File "<string>", line 2, in initialize
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/Users/tom/Library/Python/3.4/lib/python/site-packages/jupyterhub/app.py", line 587, in initialize
    super(JupyterHubApp, self).initialize(*args, **kwargs)
  File "<string>", line 2, in initialize
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 256, in initialize
    self.parse_command_line(argv)
  File "<string>", line 2, in parse_command_line
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 499, in parse_command_line
    self.update_config(config)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 398, in update_config
    self.config = newconfig
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/utils/traitlets.py", line 371, in __set__
    obj._notify_trait(self.name, old_value, new_value)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/utils/traitlets.py", line 520, in _notify_trait
    c(name, old_value, new_value)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 248, in _config_changed
    self.log.debug(repr(new))
Message: "{'JupyterHubApp': {'log_level': 10}}"
Arguments: ()
--- Logging error ---
Traceback (most recent call last):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 971, in emit
    msg = self.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 821, in format
    return fmt.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 121, in format
    return super(LevelFormatter, self).format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 561, in format
    s = self.formatMessage(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 530, in formatMessage
    return self._style.format(record)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/logging/__init__.py", line 374, in format
    return self._fmt % record.__dict__
KeyError: 'color'
Call stack:
  File "/Users/tom/Library/Python/3.4/bin/jupyterhub", line 4, in <module>
    main()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 563, in launch_instance
    app.initialize(argv)
  File "<string>", line 2, in initialize
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/Users/tom/Library/Python/3.4/lib/python/site-packages/jupyterhub/app.py", line 590, in initialize
    self.load_config_file(self.config_file)
  File "<string>", line 2, in load_config_file
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 92, in catch_config_error
    return method(app, *args, **kwargs)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 538, in load_config_file
    for config in self._load_config_files(filename, path=path, log=self.log):
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/IPython/config/application.py", line 527, in _load_config_files
    log.debug("Loaded config file: %s", loader.full_filename)
Message: 'Loaded config file: %s'
Arguments: ('/Users/tom/jupyter_hub_config.py',)
[I 20:55:19.251 JupyterHubApp] Not using whitelist. Any authenticated user will be allowed.
[D 20:55:19.254 JupyterHubApp] Loaded users: 
         tom admin
[I 20:55:19.262 JupyterHubApp] Starting proxy: ['configurable-http-proxy', '--ip', '', '--port', '8000', '--api-ip', 'localhost', '--api-port', '8001', '--default-target', 'http://localhost:8081', '--log-level', 'debug']
20:55:19.360 - info: [ConfigProxy] Proxying http://*:8000 to http://localhost:8081
20:55:19.363 - info: [ConfigProxy] Proxy API at http://localhost:8001/api/routes
[D 20:55:19.370 JupyterHubApp] Proxy started and appears to be up
[I 20:55:37.148 tornado.access] 302 GET / (::1) 0.81ms
[I 20:55:37.153 tornado.access] 302 GET /hub/ (::1) 3.58ms
[E 20:55:37.177 tornado.general] Could not open static file '/Users/tom/Library/Python/3.4/share/jupyter/static/images/favicon.ico'
[I 20:55:37.178 tornado.access] 304 GET /hub/home (::1) 23.17ms
[I 20:55:37.285 tornado.access] 304 GET /hub/static/js/home.js (::1) 6.52ms
[I 20:55:37.299 tornado.access] 304 GET /hub/static/js/jhapi.js (::1) 0.84ms
[I 20:55:37.302 tornado.access] 304 GET /hub/static/js/utils.js (::1) 0.49ms
[I 20:55:38.002 tornado.access] 302 GET / (::1) 0.42ms
[I 20:55:38.053 tornado.access] 302 GET /hub/ (::1) 4.03ms
[I 20:55:38.060 tornado.access] 304 GET /hub/home (::1) 4.97ms
[I 20:55:39.766 JupyterHubApp] Spawning ['jupyterhub-singleuser', '--user=tom', '--port=56102', '--cookie-name=jupyter-hub-token-tom', '--base-url=/user/tom', '--hub-prefix=/hub/', '--hub-api-url=http://localhost:8081/hub/api']
[D 20:55:39.770 JupyterHubApp] Polling subprocess every 30s
2014-10-03 20:55:40.337 [SingleUserNotebookApp] Using existing profile dir: '/Users/tom/.ipython/profile_default'
2014-10-03 20:55:40.361 [SingleUserNotebookApp] Using MathJax from CDN: https://cdn.mathjax.org/mathjax/latest/MathJax.js
2014-10-03 20:55:40.376 [SingleUserNotebookApp] Serving notebooks from local directory: /Users/tom
2014-10-03 20:55:40.377 [SingleUserNotebookApp] 0 active kernels 
2014-10-03 20:55:40.377 [SingleUserNotebookApp] The IPython Notebook is running at: http://localhost:56102/user/tom/
2014-10-03 20:55:40.377 [SingleUserNotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[I 20:55:40.391 JupyterHubApp] Adding user tom to proxy /user/tom => http://localhost:56102
[D 20:55:40.396 JupyterHubApp] Fetching POST http://localhost:8001/api/routes/user/tom
20:55:40.402 - debug: [ConfigProxy] POST /user/tom user=tom, target=http://localhost:56102
[I 20:55:40.412 tornado.access] 302 GET /hub/user/tom/ (::1) 670.11ms
[I 20:55:40.415 tornado.access] 302 GET /user/tom/ (::1) 0.39ms
[I 20:55:40.424 tornado.access] 302 GET /hub/user/tom/ (::1) 7.74ms
[I 20:55:40.427 tornado.access] 302 GET /user/tom/ (::1) 0.31ms
[I 20:55:40.437 tornado.access] 302 GET /hub/user/tom/ (::1) 7.91ms
[I 20:55:40.440 tornado.access] 302 GET /user/tom/ (::1) 0.35ms
[I 20:55:40.452 tornado.access] 302 GET /hub/user/tom/ (::1) 9.30ms
[I 20:55:40.455 tornado.access] 302 GET /user/tom/ (::1) 0.37ms
[I 20:55:40.467 tornado.access] 302 GET /hub/user/tom/ (::1) 7.75ms
[I 20:55:40.469 tornado.access] 302 GET /user/tom/ (::1) 0.44ms
[I 20:55:40.479 tornado.access] 302 GET /hub/user/tom/ (::1) 8.52ms
[I 20:55:40.482 tornado.access] 302 GET /user/tom/ (::1) 0.31ms
[I 20:55:40.492 tornado.access] 302 GET /hub/user/tom/ (::1) 8.20ms
[I 20:55:40.495 tornado.access] 302 GET /user/tom/ (::1) 0.33ms
[I 20:55:40.504 tornado.access] 302 GET /hub/user/tom/ (::1) 7.79ms
[I 20:55:40.507 tornado.access] 302 GET /user/tom/ (::1) 0.34ms
[I 20:55:40.518 tornado.access] 302 GET /hub/user/tom/ (::1) 8.60ms
```

Ah, you are using IPython 2.x. It kinda sorta works, but won't be supported by the time we get around to making a release. Can you see if it works with IPython master?

Huh, I thought I was using Python 3.4 - which bit of the log are you referring to? I'll try and install IPython master to see if it works.

@minrk - no luck with IPython dev, but this is interesting: the log suggests the notebook is running at http://localhost:56461/user/tom/ but if I go to http://localhost:56461/user/tom/ I get a custom 404 that says `404: Not Found`. And even http://localhost:56461 returns a 404.

And when you upgrade to IPython dev, you no longer see the KeyErrors, correct? If you do, it's not actually using IPython dev.

Do you have any IPython notebook config in your user's default profile? What do you get from `which -a jupyterhub-singleuser`?

@minrk - right, the KeyErrors are no longer there. But there is progress - if I click on My Server it still goes in a redirect loop as before, bit if I go to the notebook URL I get a 404 page formatted notebook-style:

![screen shot 2014-10-03 at 11 25 35 pm](https://cloud.githubusercontent.com/assets/314716/4512736/d41a420a-4b43-11e4-9d02-10281a76cc1c.png)

and if I go to http://localhost:59266/user/tom/ I can see a normal notebook view. But I just don't get redirected there from the jupyter hub.

@minrk @astrofrog I have a similar error running py27 on ubuntu 14.04.1 with sqlalchemy-dev and ipython-dev. If there is any debug log needed I'm happy to help. 


Resolving patch:
diff --git a/jupyterhub/orm.py b/jupyterhub/orm.py
--- a/jupyterhub/orm.py
+++ b/jupyterhub/orm.py
@@ -314,10 +314,10 @@ def spawn(self, spawner_class, base_url='/', hub=None, config=None):
             config=config,
             user=self,
             hub=hub,
-            api_token=api_token.token,
         )
         # we are starting a new server, make sure it doesn't restore state
         spawner.clear_state()
+        spawner.api_token = api_token.token
         
         yield spawner.start()
         spawner.start_polling()
diff --git a/jupyterhub/spawner.py b/jupyterhub/spawner.py
--- a/jupyterhub/spawner.py
+++ b/jupyterhub/spawner.py
@@ -98,7 +98,7 @@ def load_state(self, state):
         
         get_state, clear_state
         """
-        if 'api_token' in state:
+        if state.get('api_token'):
             self.api_token = state['api_token']
     
     def get_state(self):


Test patch: