Page MenuHomeSoftware Heritage

Investigate tower decorator breaking production in web-ui
Closed, MigratedEdits Locked

Description

When deploying the latest version on archive.s.o, the commit 258b7c2302458d483fa9893495fa8be0fbef284b about the ultimate adaption on the apidoc decorator broke the production.

The fastest route was deemed to revert it (0afc244347575a80561e05c2234563bafc724a25) to stabilize the production first.

This task is to investigate what is possibly wrong in that commit to fix and commit it again.

Event Timeline

With the commit installed, here is the output that breaks the /content/search/ api.

 tony  ⋯  repo  swh  swh-environment  curl -X POST -d sha1=adc83b19e793491b1c6ea0fd8b46cd9f32e592fc http://localhost:6543/api/1/content/search/                                                                                 master 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>ValueError: View function did not return a response // Werkzeug Debugger</title>
    <link rel="stylesheet" href="?__debugger__=yes&amp;cmd=resource&amp;f=style.css"
        type="text/css">
    <!-- We need to make sure this has a favicon so that the debugger does
         not by accident trigger a request to /favicon.ico which might
         change the application state. -->
    <link rel="shortcut icon"
        href="?__debugger__=yes&amp;cmd=resource&amp;f=console.png">
    <script src="?__debugger__=yes&amp;cmd=resource&amp;f=jquery.js"></script>
    <script src="?__debugger__=yes&amp;cmd=resource&amp;f=debugger.js"></script>
    <script type="text/javascript">
      var TRACEBACK = 140514028235408,
          CONSOLE_MODE = false,
          EVALEX = true,
          EVALEX_TRUSTED = false,
          SECRET = "IMXyiKaxTPwwBSZGvlTc";
    </script>
  </head>
  <body>
    <div class="debugger">
<h1>builtins.ValueError</h1>
<div class="detail">
  <p class="errormsg">ValueError: View function did not return a response</p>
</div>
<h2 class="traceback">Traceback <em>(most recent call last)</em></h2>
<div class="traceback">

  <ul><li><div class="frame" id="frame-140514030705184">
  <h4>File <cite class="filename">"/usr/lib/python3/dist-packages/flask/app.py"</cite>,
      line <em class="line">2000</em>,
      in <code class="function">__call__</code></h4>
  <div class="source"><pre class="line before"><span class="ws">                </span>error = None</pre>
<pre class="line before"><span class="ws">            </span>ctx.auto_pop(error)</pre>
<pre class="line before"><span class="ws"></span> </pre>
<pre class="line before"><span class="ws">    </span>def __call__(self, environ, start_response):</pre>
<pre class="line before"><span class="ws">        </span>&quot;&quot;&quot;Shortcut for :attr:`wsgi_app`.&quot;&quot;&quot;</pre>
<pre class="line current"><span class="ws">        </span>return self.wsgi_app(environ, start_response)</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>def __repr__(self):</pre>
<pre class="line after"><span class="ws">        </span>return '&lt;%s %r&gt;' % (</pre>
<pre class="line after"><span class="ws">            </span>self.__class__.__name__,</pre>
<pre class="line after"><span class="ws">            </span>self.name,</pre></div>
</div>

<li><div class="frame" id="frame-140514030705912">
  <h4>File <cite class="filename">"/usr/lib/python3/dist-packages/flask/app.py"</cite>,
      line <em class="line">1991</em>,
      in <code class="function">wsgi_app</code></h4>
  <div class="source"><pre class="line before"><span class="ws">        </span>try:</pre>
<pre class="line before"><span class="ws">            </span>try:</pre>
<pre class="line before"><span class="ws">                </span>response = self.full_dispatch_request()</pre>
<pre class="line before"><span class="ws">            </span>except Exception as e:</pre>
<pre class="line before"><span class="ws">                </span>error = e</pre>
<pre class="line current"><span class="ws">                </span>response = self.make_response(self.handle_exception(e))</pre>
<pre class="line after"><span class="ws">            </span>return response(environ, start_response)</pre>
<pre class="line after"><span class="ws">        </span>finally:</pre>
<pre class="line after"><span class="ws">            </span>if self.should_ignore_error(error):</pre>
<pre class="line after"><span class="ws">                </span>error = None</pre>
<pre class="line after"><span class="ws">            </span>ctx.auto_pop(error)</pre></div>
</div>

<li><div class="frame" id="frame-140514030705464">
  <h4>File <cite class="filename">"/usr/lib/python3/dist-packages/flask/app.py"</cite>,
      line <em class="line">1567</em>,
      in <code class="function">handle_exception</code></h4>
  <div class="source"><pre class="line before"><span class="ws">            </span># if we want to repropagate the exception, we can attempt to</pre>
<pre class="line before"><span class="ws">            </span># raise it with the whole traceback in case we can do that</pre>
<pre class="line before"><span class="ws">            </span># (the function was actually called from the except part)</pre>
<pre class="line before"><span class="ws">            </span># otherwise, we just raise the error again</pre>
<pre class="line before"><span class="ws">            </span>if exc_value is e:</pre>
<pre class="line current"><span class="ws">                </span>reraise(exc_type, exc_value, tb)</pre>
<pre class="line after"><span class="ws">            </span>else:</pre>
<pre class="line after"><span class="ws">                </span>raise e</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">        </span>self.log_exception((exc_type, exc_value, tb))</pre>
<pre class="line after"><span class="ws">        </span>if handler is None:</pre></div>
</div>

<li><div class="frame" id="frame-140514030704008">
  <h4>File <cite class="filename">"/usr/lib/python3/dist-packages/flask/_compat.py"</cite>,
      line <em class="line">33</em>,
      in <code class="function">reraise</code></h4>
  <div class="source"><pre class="line before"><span class="ws">    </span>from io import StringIO</pre>
<pre class="line before"><span class="ws"></span> </pre>
<pre class="line before"><span class="ws">    </span>def reraise(tp, value, tb=None):</pre>
<pre class="line before"><span class="ws">        </span>if value.__traceback__ is not tb:</pre>
<pre class="line before"><span class="ws">            </span>raise value.with_traceback(tb)</pre>
<pre class="line current"><span class="ws">        </span>raise value</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>implements_to_string = _identity</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws"></span>else:</pre>
<pre class="line after"><span class="ws">    </span>text_type = unicode</pre></div>
</div>

<li><div class="frame" id="frame-140514030705576">
  <h4>File <cite class="filename">"/usr/lib/python3/dist-packages/flask/app.py"</cite>,
      line <em class="line">1988</em>,
      in <code class="function">wsgi_app</code></h4>
  <div class="source"><pre class="line before"><span class="ws">        </span>ctx = self.request_context(environ)</pre>
<pre class="line before"><span class="ws">        </span>ctx.push()</pre>
<pre class="line before"><span class="ws">        </span>error = None</pre>
<pre class="line before"><span class="ws">        </span>try:</pre>
<pre class="line before"><span class="ws">            </span>try:</pre>
<pre class="line current"><span class="ws">                </span>response = self.full_dispatch_request()</pre>
<pre class="line after"><span class="ws">            </span>except Exception as e:</pre>
<pre class="line after"><span class="ws">                </span>error = e</pre>
<pre class="line after"><span class="ws">                </span>response = self.make_response(self.handle_exception(e))</pre>
<pre class="line after"><span class="ws">            </span>return response(environ, start_response)</pre>
<pre class="line after"><span class="ws">        </span>finally:</pre></div>
</div>

<li><div class="frame" id="frame-140514030704680">
  <h4>File <cite class="filename">"/usr/lib/python3/dist-packages/flask/app.py"</cite>,
      line <em class="line">1642</em>,
      in <code class="function">full_dispatch_request</code></h4>
  <div class="source"><pre class="line before"><span class="ws">            </span>rv = self.preprocess_request()</pre>
<pre class="line before"><span class="ws">            </span>if rv is None:</pre>
<pre class="line before"><span class="ws">                </span>rv = self.dispatch_request()</pre>
<pre class="line before"><span class="ws">        </span>except Exception as e:</pre>
<pre class="line before"><span class="ws">            </span>rv = self.handle_user_exception(e)</pre>
<pre class="line current"><span class="ws">        </span>response = self.make_response(rv)</pre>
<pre class="line after"><span class="ws">        </span>response = self.process_response(response)</pre>
<pre class="line after"><span class="ws">        </span>request_finished.send(self, response=response)</pre>
<pre class="line after"><span class="ws">        </span>return response</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>def try_trigger_before_first_request_functions(self):</pre></div>
</div>

<li><div class="frame" id="frame-140514030785032">
  <h4>File <cite class="filename">"/usr/lib/python3/dist-packages/flask/app.py"</cite>,
      line <em class="line">1731</em>,
      in <code class="function">make_response</code></h4>
  <div class="source"><pre class="line before"><span class="ws">        </span>status_or_headers = headers = None</pre>
<pre class="line before"><span class="ws">        </span>if isinstance(rv, tuple):</pre>
<pre class="line before"><span class="ws">            </span>rv, status_or_headers, headers = rv + (None,) * (3 - len(rv))</pre>
<pre class="line before"><span class="ws"></span> </pre>
<pre class="line before"><span class="ws">        </span>if rv is None:</pre>
<pre class="line current"><span class="ws">            </span>raise ValueError('View function did not return a response')</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">        </span>if isinstance(status_or_headers, (dict, list)):</pre>
<pre class="line after"><span class="ws">            </span>headers, status_or_headers = status_or_headers, None</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">        </span>if not isinstance(rv, self.response_class):</pre></div>
</div>
</ul>
  <blockquote>ValueError: View function did not return a response</blockquote>
</div>

<div class="plain">
  <form action="/?__debugger__=yes&amp;cmd=paste" method="post">
    <p>
      <input type="hidden" name="language" value="pytb">
      This is the Copy/Paste friendly version of the traceback.  <span
      class="pastemessage">You can also paste this traceback into
      a <a href="https://gist.github.com/">gist</a>:
      <input type="submit" value="create paste"></span>
    </p>
    <textarea cols="50" rows="10" name="code" readonly>Traceback (most recent call last):
  File &quot;/usr/lib/python3/dist-packages/flask/app.py&quot;, line 2000, in __call__
    return self.wsgi_app(environ, start_response)
  File &quot;/usr/lib/python3/dist-packages/flask/app.py&quot;, line 1991, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File &quot;/usr/lib/python3/dist-packages/flask/app.py&quot;, line 1567, in handle_exception
    reraise(exc_type, exc_value, tb)
  File &quot;/usr/lib/python3/dist-packages/flask/_compat.py&quot;, line 33, in reraise
    raise value
  File &quot;/usr/lib/python3/dist-packages/flask/app.py&quot;, line 1988, in wsgi_app
    response = self.full_dispatch_request()
  File &quot;/usr/lib/python3/dist-packages/flask/app.py&quot;, line 1642, in full_dispatch_request
    response = self.make_response(rv)
  File &quot;/usr/lib/python3/dist-packages/flask/app.py&quot;, line 1731, in make_response
    raise ValueError('View function did not return a response')
ValueError: View function did not return a response</textarea>
  </form>
</div>
<div class="explanation">
  The debugger caught an exception in your WSGI application.  You can now
  look at the traceback which led to the error.  <span class="nojavascript">
  If you enable JavaScript you can also use additional features such as code
  execution (if the evalex feature is enabled), automatic pasting of the
  exceptions and much more.</span>
</div>
      <div class="footer">
        Brought to you by <strong class="arthur">DON'T PANIC</strong>, your
        friendly Werkzeug powered traceback interpreter.
      </div>
    </div>

    <div class="pin-prompt">
      <div class="inner">
        <h3>Console Locked</h3>
        <p>
          The console is locked and needs to be unlocked by entering the PIN.
          You can find the PIN printed out on the standard output of your
          shell that runs the server.
        <form>
          <p>PIN:
            <input type=text name=pin size=14>
            <input type=submit name=btn value="Confirm Pin">
        </form>
      </div>
    </div>
  </body>
</html>

<!--

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/flask/app.py", line 2000, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1991, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1567, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib/python3/dist-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1988, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1642, in full_dispatch_request
    response = self.make_response(rv)
  File "/usr/lib/python3/dist-packages/flask/app.py", line 1731, in make_response
    raise ValueError('View function did not return a response')
ValueError: View function did not return a response

-->

It's not quite completely clear yet but, in that commit, this function call fails because:

  • it's a post call (only one, that's why it might have not been seen yet) -> fortunately for us, this is the open production one :)
  • the runtime path is assimilated to a documentation call (thus returning None as a result).
ardumont renamed this task from What is wrong with commit 258b7c2302458d483fa9893495fa8be0fbef284b? to Investigate tower decorator breaking production in web-ui.Nov 23 2016, 12:12 PM
ardumont claimed this task.
ardumont updated the task description. (Show Details)