3599: certain search string causes "Error 500"

dccarson
Feb. 11, 2015
3677
What version are you running?
2.0.8
Server is running CentOS 7.

What's the URL of the page containing the problem?
http://reviewboard.mycompany.com/r/search/?q=test

What steps will reproduce the problem?
1. Search for string "test"  
NOTE that other searches work.

What is the expected output? What do you see instead?
I expect a list of links to review requests containing the string "test".  There are definitely review requests that contain the string "test".

Instead, I get this:

Something broke! (Error 500)

It appears something broke when you tried to go to here. This is either a bug in Review Board or a server configuration error. Please report this to your administrator.

What operating system are you using? What browser?
OS: Mac OSX 10.9 -- However, this has been confirmed on Windows and Linux as well.
Browser: Chrome


Please provide any additional information below.
I'm setting up a new RB deployment -- version 2.0.8 on CentOS 7.

We have 20 or so test review requests that were created by the beta testers.  When I search for most strings, I get the expected list of links.  However, when I search for a certain string ("test"), I get a "Something broke! (Error 500)" error.

Since the error is the following (snippet of full traceback):

File "/usr/lib/python2.7/site-packages/djblets/util/templatetags/djblets_utils.py", line 203, in user_displayname
  return user.get_full_name() or user.username
AttributeError: 'str' object has no attribute 'get_full_name'



I thought, "Oh, I know what this is."  Some of the new users (NIS) are being created without a last name, because some of our NIS entries have "last, first" in the fullname field.  So, I fixed those users as the admin, by adding the correct first and last name.  

Alas, that did not fix it.  I'm still getting the same error.  Is there something else that I need to do to 'flush' this change out of a buffer or something??

Here is the full traceback:

Traceback (most recent call last):

  File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py", line 112, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)

  File "/usr/lib/python2.7/site-packages/django/utils/decorators.py", line 29, in _wrapper
    return bound_func(*args, **kwargs)

  File "/usr/lib/python2.7/site-packages/reviewboard/accounts/decorators.py", line 23, in _check
    return view_func(*args, **kwargs)

  File "/usr/lib/python2.7/site-packages/django/utils/decorators.py", line 25, in bound_func
    return func(self, *args2, **kwargs2)

  File "/usr/lib/python2.7/site-packages/django/utils/decorators.py", line 29, in _wrapper
    return bound_func(*args, **kwargs)

  File "/usr/lib/python2.7/site-packages/reviewboard/site/decorators.py", line 35, in _check
    return view_func(request, local_site=local_site, *args, **kwargs)

  File "/usr/lib/python2.7/site-packages/django/utils/decorators.py", line 25, in bound_func
    return func(self, *args2, **kwargs2)

  File "/usr/lib/python2.7/site-packages/reviewboard/reviews/views.py", line 1475, in __call__
    return super(ReviewRequestSearchView, self).__call__(request)

  File "/usr/lib/python2.7/site-packages/haystack/views.py", line 50, in __call__
    return self.create_response()

  File "/usr/lib/python2.7/site-packages/reviewboard/reviews/views.py", line 1520, in create_response
    context_instance=self.context_class(self.request))

  File "/usr/lib/python2.7/site-packages/django/shortcuts/__init__.py", line 29, in render_to_response
    return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)

  File "/usr/lib/python2.7/site-packages/django/template/loader.py", line 169, in render_to_string
    return t.render(context_instance)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 140, in render
    return self._render(context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
    return self.nodelist.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
    return node.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py", line 123, in render
    return compiled_parent._render(context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
    return self.nodelist.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
    return node.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
    return node.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 840, in render
    bit = self.render_node(node, context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 854, in render_node
    return node.render(context)

  File "/usr/lib/python2.7/site-packages/django/template/defaulttags.py", line 203, in render
    nodelist.append(node.render(context))

  File "/usr/lib/python2.7/site-packages/django/templatetags/i18n.py", line 127, in render
    tmp_context[var] = val.resolve(context)

  File "/usr/lib/python2.7/site-packages/django/template/base.py", line 613, in resolve
    new_obj = func(obj, *arg_vals)

  File "/usr/lib/python2.7/site-packages/djblets/util/templatetags/djblets_utils.py", line 203, in user_displayname
    return user.get_full_name() or user.username

AttributeError: 'str' object has no attribute 'get_full_name'


<WSGIRequest
path:/r/search/,
GET:<QueryDict: {u'q': [u'test']}>,
POST:<QueryDict: {}>,
COOKIES:{'collapsediffs': 'True',
'csrftoken': 'Et9WvlrHMs8PVcvrEUBGiMSju4jL6yz9',
'rbsessionid': 'mbj0vgf66eviveznsx1ibsmzr05uenoa'},
META:{'CONTEXT_DOCUMENT_ROOT': '/var/www/ReviewBoard/htdocs',
'CONTEXT_PREFIX': '',
'DOCUMENT_ROOT': '/var/www/ReviewBoard/htdocs',
'GATEWAY_INTERFACE': 'CGI/1.1',
'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'HTTP_ACCEPT_ENCODING': 'gzip,deflate,sdch',
'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.8',
'HTTP_CONNECTION': 'keep-alive',
'HTTP_COOKIE': 'rbsessionid=mbj0vgf66eviveznsx1ibsmzr05uenoa; collapsediffs=True; csrftoken=Et9WvlrHMs8PVcvrEUBGiMSju4jL6yz9',
'HTTP_HOST': 'reviewboard',
'HTTP_REFERER': 'http://reviewboard/r/',
'HTTP_USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36',
u'LOCAL_SITE': None,
'PATH_INFO': u'/r/search/',
'PATH_TRANSLATED': '/var/www/ReviewBoard/htdocs/reviewboard.wsgi/r/search/',
'QUERY_STRING': 'q=test',
'REMOTE_ADDR': '10.6.105.68',
'REMOTE_PORT': '64297',
'REQUEST_METHOD': 'GET',
'REQUEST_SCHEME': 'http',
'REQUEST_URI': '/r/search/?q=test',
'SCRIPT_FILENAME': '/var/www/ReviewBoard/htdocs/reviewboard.wsgi',
'SCRIPT_NAME': u'',
'SERVER_ADDR': '10.68.9.34',
'SERVER_ADMIN': 'build-sc@mycompany.com',
'SERVER_NAME': 'reviewboard',
'SERVER_PORT': '80',
'SERVER_PROTOCOL': 'HTTP/1.1',
'SERVER_SIGNATURE': '',
'SERVER_SOFTWARE': 'Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips mod_fcgid/2.3.9 mod_wsgi/3.4 Python/2.7.5',
'UNIQUE_ID': 'VC3ABUR8wqq0n1A1GiE3qQAAAAw',
u'USERNAME': u'dcarson',
u'USER_EMAIL': u'dcarson@mycompany.com',
'mod_wsgi.application_group': 'pinehurst.mycompany.com|',
'mod_wsgi.callable_object': 'application',
'mod_wsgi.enable_sendfile': '0',
'mod_wsgi.handler_script': '',
'mod_wsgi.input_chunked': '0',
'mod_wsgi.listener_host': '',
'mod_wsgi.listener_port': '80',
'mod_wsgi.process_group': '',
'mod_wsgi.queue_start': '1412284421095998',
'mod_wsgi.request_handler': 'wsgi-script',
'mod_wsgi.script_reloading': '1',
'mod_wsgi.version': (3, 4),
'wsgi.errors': <mod_wsgi.Log object at 0x7f03cd6d5630>,
'wsgi.file_wrapper': <built-in method file_wrapper of mod_wsgi.Adapter object at 0x7f03cd630300>,
'wsgi.input': <mod_wsgi.Input object at 0x7f03cd6c0330>,
'wsgi.multiprocess': True,
'wsgi.multithread': False,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0)}>
#2 dccarson
In order to allow our deployment to begin, I protected the code in question.  It will return "Unknown (%s)" % user, if 'user' is a string instead of an object with the "get_full_name()" method.

Now, I get the expected matches, and also a few of these (just the last line that gives the time and user):

    NaN years, NaN months ago by Unknown ()

Apparently, I have a few corrupted requests in my database.  How might I go about finding them?  When I look at "Review Requests" under admin->Database->Reviews->ReviewRequests, I see only requests with real users and real dates.
david
#3 david
It sounds like something is actually corrupted in your search index. Have you tried doing a full reindex?
  • +NeedInfo
#5 sour*****@gmai***** (Google Code) (Is this you? Claim this profile.)
We rebuild our index once a week still and have been seeing this issue for more than a month (can't give a precise time on when it started sorry). Any other ideas?
#6 dccarson
I would like to renew my request for more information on how to find the offending records in the database (assuming that is actually what is causing the issue).  This problem continues to hit us and requires that I reapply my hack after each upgrade of ReviewBoard.

I've looked at:
- the auth_user table, looking for corrupted usernames
- reviews_reviewrequest table, searching for any requests where the submitter_id is outside the range of valid users

Absent any ideas on finding the offending records, perhaps suggestions on how to collect more useful information at the point of the exception would be useful.  At the moment, I am detecting the failed condition in djblets/util/templatetags/djblets_utils.py:user_displayname(), which itself does not have access to anything but the 'user' object being passed in.  This is no help in locating the associated review request -- especially as it appears to be an empty string.

By the way, I am currently running version 2.0.12 of ReviewBoard and 0.8.14-1 of python-djblets.

Thanks.
david
#7 david
After looking into this more, I'm pretty sure it's not corruption in the database, but I'm still not sure why we're getting bad results from Haystack. I'm going to try adding some more bullet-proofing to the search results template.
  • -NeedInfo
    +Started
david
#8 david
Fixed (hopefully) in release-2.0.x (e929016). Please let us know if 2.0.13 doesn't solve this.
  • -Started
    +Fixed
#9 dccarson
I'll try 2.0.13 as soon as it's out and let you know.  Thanks for the quick response time.
#10 trivia21

How can I get the patch of this bug.

david
#11 david

It's in all versions 2.0.13 and greater, or you can go to https://github.com/reviewboard/reviewboard/commit/e929016

#12 trivia21

Thanks David.