Break on unhandled exception not working

Mar 6, 2013 at 4:53 PM
I am doing google app engine development, but I think the question applies in general. I have break on unhandled exceptions checked, but the debugger does not break. Has anyone encountered this?

If I check the box to break when exception is thrown, the debugger breaks.
Coordinator
Mar 6, 2013 at 9:59 PM
Two things to check. The first is whether you have Just My Code enabled (Tools->Options->Debugging). When this is enabled, you will see two check boxes, and the second thing to check is whether the "User-unhandled" box is checked (some errors are unchecked by default, such as StopIteration and AttributeError, because we can't always detect when they are handled).

Which exception types are you expecting to see?
Mar 9, 2013 at 12:46 AM
  1. Just My Code is enabled
  2. "User-unhandled" box is checked
    but debugger does not break on unhandled exception
Coordinator
Mar 9, 2013 at 9:17 PM
Is that the User-unhandled box for the specific exception we're not breaking on? Each exception can have its own setting, and some default to unchecked even when the top-level box is checked.

Do you have a script that we can test? Ideally with as little code as possible to isolate the problem.
Mar 10, 2013 at 10:17 PM
Edited Mar 10, 2013 at 10:18 PM
Hi,

Yes - the User-unhandled box for the specific exception we're not breaking on is checked.

I am happy to provide sample test code (sorry for long post).
  1. Create a directory
  2. Create two files main.py and app.yaml
    app.yaml:
application: mytestapp
version: 1
runtime: python27
threadsafe: true
api_version: 1
default_expiration: "5d 12h"

handlers:
- url: /.*
  script: main.app
main.py:
import webapp2

class Index(webapp2.RequestHandler):
    def get(self):
        self.response.out.write('hello world!')        

mappings = [('/', 'main.Index')]
app = webapp2.WSGIApplication(mappings)
  1. Launch VS. Create Python application from existing code.
  2. Add above two files to the project
  3. Alt->ENTER->General. Set Startup File to C:\Program Files (x86)\Google\google_appengine\dev_appserver.py
  4. Alt->ENTER->Debug. Set Script Arguments to directory in step 1
  5. F5
  6. Verify this output in python shell:
    INFO 2013-03-10 15:07:15,349 appcfg.py:618] Checking for updates to the SDK.
INFO 2013-03-10 15:07:16,717 appcfg.py:636] The SDK is up to date.
WARNING 2013-03-10 15:07:16,720 dev_appserver.py:3578] The datastore file stub
is deprecated, and
will stop being the default in a future release.
Append the --use_sqlite flag to use the new SQLite stub.

You can port your existing data using the --port_sqlite_data flag or
purge your previous test data with --clear_datastore.

WARNING 2013-03-10 15:07:16,779 simple_search_stub.py:975] Could not read searc
h indexes from c:\users\me\appdata\local\temp\dev_appserver.searchindexes
INFO 2013-03-10 15:07:17,049 dev_appserver_multiprocess.py:656] __Running appl
ication dev~mytestapp on port 8080: http://localhost:8080__ INFO 2013-03-10 15:07:17,052 dev_appserver_multiprocess.py:658] Admin consol
e is available at: http://localhost:8080/_ah/admin
  1. Open web browser, navigate to http://localhost:8080/
  2. Verify web page that says hello world!
Now to break above code to test if debugger is breaking on unhandled exception, simply change
mappings = [('/', 'main.Index')]
to
mappings = [('/', 'Index')]

Now if you refresh the webpage, you will see:
500 Internal Server Error

The server has either erred or is incapable of performing the requested operation.

Python shell will show:
ERROR 2013-03-10 15:10:17,605 webapp2.py:1552] import_string() failed for 'In
dex'. Possible reasons are:
  • missing init.py in a package;
  • package or module path not included in sys.path;
  • duplicated package or module name taking precedence in sys.path;
  • missing module, class, function or variable;
Original exception:

ImportError: No module named Index

Debugged import:
  • 'Index' not found.
    Traceback (most recent call last):
    File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2
    .py", line 1535, in call
    rv = self.handle_exception(request, response, e)
    File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2
    .py", line 1529, in call
    rv = self.router.dispatch(request, response)
    File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2
    .py", line 1272, in default_dispatcher
    self.handlers[handler] = handler = import_string(handler)
    File "C:\Program Files (x86)\Google\google_appengine\lib\webapp2-2.5.2\webapp2
    .py", line 1852, in import_string
    return __import__(import_name)
    ImportStringError: import_string() failed for 'Index'. Possible reasons are:
  • missing init.py in a package;
  • package or module path not included in sys.path;
  • duplicated package or module name taking precedence in sys.path;
  • missing module, class, function or variable;
Original exception:

ImportError: No module named Index

Debugged import:
  • 'Index' not found.
    INFO 2013-03-10 15:10:17,674 dev_appserver.py:3104] "GET / HTTP/1.1" 500 -
Is VS debugger not breaking because as far as it is concerned this is not a user-unhandled exception? Any way so that VS debugger breaks before exception is handled by dev_appserver.py?
Coordinator
Mar 11, 2013 at 4:26 PM
You're right - because we see that the exception is going to be handled we won't break.

Right now the only way to change this is to always break. I believe we can find the AppEngine code and determine exactly which exceptions are being handled, but if we couldn't find the code then we would assume that all exceptions are handled (the aim being to never have a false-positive, since that causes an interruption).

I guess we're not following the "User-unhandled" label properly, since the user isn't handling the exception and yet we're not breaking. It would be nice if VS would let us have a third option, but when we designed the feature we decided that breaking too often would cause people to turn off the feature and lose the benefits. We turned off some exceptions ourselves for the same reason - this is why AttributeErrors and IndexErrors (and a few others) won't break even if they're unhandled.

Hope that clears things up a bit.