Description
Context
A somewhat common and mystifying error that new zappa devs run into is the "NoneType is not callable" There are a few ways we could make this clearer, so I just wanted to make an issue talking about where this occurs and see what the right way to solve it is.
Expected Behavior
When an error occurs, provide appropriate and helpful messaging.
Actual Behavior
When zappa fails to load the underlying application, it stores the application as None. Subsequent calls to the application yield the error above.
During handler initialization, the self.wsgi_app property gets set here: https://github.com/Miserlou/Zappa/blob/master/zappa/handler.py#L129
Initial calls to the handler yield a 500 server error, this is different from the NoneType error above, but most devs never encounter this due to zappa's "touch": true default setting. This error is encountered by zappa and not the dev.
Because the warm handler is reused, the self.wsgi_app property is None (handler initialization crashed during touch/cold-start). The handler has already been initialized, and so crashes when it attempts to get a response from this app:
https://github.com/Miserlou/Zappa/blob/master/zappa/handler.py#L448
Possible Fix
There are quite a few reasons why the app my not load. While missing packages is the most common I've experienced and seen on slack/issues, it certainly isn't the only one. So fixing this gets a little tricky. Currently we just tell people to look at zappa tail. This honestly answers most of the questions but it feels like some people either don't do it until told by the community or have difficulty in debugging the error it printed out. So there are a few possible fixes with the sole aim of helping people debug.
-
Do nothing. We tell people already to check out zappa tail and they might just need to put in the hard work of debugging.
-
For the most part, these errors are caused by ImportErrors that get raised up to the tail end of the init() method. We could catch ImportErrors and provide slightly better reporting in the response. Import errors are usually a result of the environment differences between lambda, their local package, and the packages that we put on lambda via manywheel or Miserlou/lambda-packages.
-
We could check in the handle() method if self.wsgi_app exists and provide a little more explicit response there.
-
We could attampt to call the handler during
zappa update/zappa deploywith the pre-zipped project directory in an attempt to encounter any import errors prior to deployment. This might not work though because the packages that we're testing against were meant for Lambda and not the local environment. Might cause more issues than it solves.
Steps to Reproduce
- Deploy the example app: https://github.com/Miserlou/Zappa/tree/master/example
- Add a line to the app.py file to
import some_unknown_package - Call
zappa updateto put the missing package code online
Your Environment
- Zappa version used: 0.43.2
- Operating System and Python version: OSX