Upgrade Notes

This document provides additional documentation on upgrading your version of chalice. If you’re just interested in the high level changes, see the CHANGELOG.rst) file.


This release features a rewrite of the Chalice deployer (#604). This is a backwards compatible change, and should not have any noticeable changes with deployments with the exception of fixing deployer bugs (e.g. https://github.com/aws/chalice/issues/604). This code path affects the chalice deploy, chalice delete, and chalice package commands.

While this release is backwards compatible, you will notice several changes when you upgrade to version 1.2.0.

The output of chalice deploy has changed in order to give more details about the resources it creates along with a more detailed summary at the end:

$ chalice deploy
Creating deployment package.
Creating IAM role: myapp-dev
Creating lambda function: myapp-dev-foo
Creating lambda function: myapp-dev
Creating Rest API
Resources deployed:
  - Lambda ARN: arn:aws:lambda:us-west-2:12345:function:myapp-dev-foo
  - Lambda ARN: arn:aws:lambda:us-west-2:12345:function:myapp-dev
  - Rest API URL: https://abcd.execute-api.us-west-2.amazonaws.com/api/

Also, the files used to store deployed values has changed. These files are used internally by the chalice deploy/delete commands and you typically do not interact with these files directly. It’s mentioned here in case you notice new files in your .chalice directory. Note that these files are not part of the public interface of Chalice and are documented here for completeness and to help with debugging issues.

In versions < 1.2.0, the value of deployed resources was stored in .chalice/deployed.json and looked like this:

  "dev": {
    "region": "us-west-2",
    "api_handler_name": "demoauth4-dev",
    "api_handler_arn": "arn:aws:lambda:us-west-2:123:function:myapp-dev",
    "rest_api_id": "abcd",
    "lambda_functions": {
      "myapp-dev-foo": {
        "type": "pure_lambda",
        "arn": "arn:aws:lambda:us-west-2:123:function:myapp-dev-foo"
    "chalice_version": "1.1.1",
    "api_gateway_stage": "api",
    "backend": "api"
  "prod": {...}

In version 1.2.0, the deployed resources are split into multiple files, one file per chalice stage. These files are in the .chalice/deployed/<stage.json>, so if you had a dev and a prod chalice stage you’d have .chalice/deployed/dev.json and .chalice/deployed/prod.json. The schema has also changed and looks like this:

$ cat .chalice/deployed/dev.json
  "schema_version": "2.0",
  "resources": [
      "role_name": "myapp-dev",
      "role_arn": "arn:aws:iam::123:role/myapp-dev",
      "name": "default-role",
      "resource_type": "iam_role"
      "lambda_arn": "arn:aws:lambda:us-west-2:123:function:myapp-dev-foo",
      "name": "foo",
      "resource_type": "lambda_function"
      "lambda_arn": "arn:aws:lambda:us-west-2:123:function:myapp-dev",
      "name": "api_handler",
      "resource_type": "lambda_function"
      "name": "rest_api",
      "rest_api_id": "abcd",
      "rest_api_url": "https://abcd.execute-api.us-west-2.amazonaws.com/api",
      "resource_type": "rest_api"
  "backend": "api"

When you run chalice deploy for the first time after upgrading to version 1.2.0, chalice will automatically converted .chalice/deployed.json over to the format as you deploy a given stage.


Once you upgrade to 1.2.0, chalice will only update the new .chalice/deployed/<stage>.json. This means you cannot downgrade to earlier versions of chalice unless you manually update .chalice/deployed.json as well.

The chalice package command has also been updated to use the deployer. This results in several changes compared to the previous version:

  • Pure lambdas are supported

  • Scheduled events are supported

  • Parity between the behavior of chalice deploy and chalice package

As part of this change, the CFN resource names have been updated to use CamelCase names. Previously, chalice converted your python function names to CFN resource names by removing all non alphanumeric characters and appending an md5 checksum, e.g my_function -> myfunction3bfc. With this new packager update, the resource name would be converted as my_function -> MyFunction. Note, the Outputs section renames unchanged in order to preserve backwards compatibility. In order to fix parity issues with chalice deploy and chalice package, we now explicitly create an IAM role resource as part of the default configuration.


The url parameter names and the function argument names must match. Previously, the routing code would use positional args handler(*args) to invoke a view function. In this version, kwargs are now used instead: handler(**view_args). For example, this code will no longer work:

def myview(first, second)
    return {}

The example above must be updated to:

def myview(a, b)
    return {}

Now that functions are invoked with kwargs, the order doesn’t matter. You may also write the above view function as:

def myview(b, a)
    return {}

This was done to have consistent behavior with other web frameworks such as Flask.


The Chalice.define_authorizer method has been removed. This has been deprecated since v0.8.1. See Authorization for updated information on configuring authorizers in Chalice as well as the original deprecation notice in the 0.8.1 upgrade notes.

The optional deprecated positional parameter in the chalice deploy command for specifying the API Gateway stage has been removed. If you want to specify the API Gateway stage, you can use the --api-gateway-stage option in the chalice deploy command:

# Deprecated and removed in 1.0.0b1
$ chalice deploy prod

# Equivalent and updated way to specify an API Gateway stage:
$ chalice deploy --api-gateway-stage prod


The 0.9.0 release changed the type of app.current_request.raw_body to always be of type bytes(). This only affects users that were using python3. Previously you would get a type str(), but with the introduction of binary content type support, the raw_body attribute was made to consistently be of type bytes().


The 0.8.1 changed the preferred way of specifying authorizers for view functions. You now specify either an instance of chalice.CognitoUserPoolAuthorizer or chalice.CustomAuthorizer to an @app.route() function using the authorizer argument.


@app.route('/user-pools', methods=['GET'], authorizer_name='MyPool')
def authenticated():
    return {"secure": True}


Equivalent, and preferred way

from chalice import CognitoUserPoolAuthorizer

authorizer = CognitoUserPoolAuthorizer(
    'MyPool', header='Authorization',

@app.route('/user-pools', methods=['GET'], authorizer=authorizer)
def authenticated():
    return {"secure": True}

The define_authorizer is still available, but is now deprecated and will be removed in future versions of chalice. You can also use the new authorizer argument to provider a CustomAuthorizer:

from chalice import CustomAuthorizer

authorizer = CustomAuthorizer(
    'MyCustomAuth', header='Authorization',

@app.route('/custom-auth', methods=['GET'], authorizer=authorizer)
def authenticated():
    return {"secure": True}


The 0.7.0 release adds several major features to chalice. While the majority of these features are introduced in a backwards compatible way, there are a few backwards incompatible changes that were made in order to support these new major features.

Separate Stages

Prior to this version, chalice had a notion of a “stage” that corresponded to an API gateway stage. You can create and deploy a new API gateway stage by running chalice deploy <stage-name>. In 0.7.0, stage support was been reworked such that a chalice stage is a completely separate set of AWS resources. This means that if you have two chalice stages, say dev and prod, then you will have two separate sets of AWS resources, one set per stage:

  • Two API Gateway Rest APIs

  • Two separate Lambda functions

  • Two separate IAM roles

The Chalice Stages doc has more details on the new chalice stages feature. This section highlights the key differences between the old stage behavior and the new chalice stage functionality in 0.7.0. In order to ease transition to this new model, the following changes were made:

  • A new --stage argument was added to the deploy, logs, url, generate-sdk, and package commands. If this value is specified and the stage does not exist, a new chalice stage with that name will be created for you.

  • The existing form chalice deploy <stage-name> has been deprecated. The command will still work in version 0.7.0, but a deprecation warning will be printed to stderr.

  • If you want the pre-existing behavior of creating a new API gateway stage (while using the same Lambda function), you can use the --api-gateway-stage argument. This is the replacement for the deprecated form chalice deploy <stage-name>.

  • The default stage if no --stage option is provided is dev. By defaulting to a dev stage, the pre-existing behavior of not specifying a stage name, e.g chalice deploy, chalice url, etc. will still work exactly the same.

  • A new stages key is supported in the .chalice/config.json. This allows you to specify configuration specific to a chalice stage. See the Configuration File doc for more information about stage specific configuration.

  • Setting autogen_policy to false will result in chalice looking for a IAM policy file named .chalice/policy-<stage-name>.json. Previously it would look for a file named .chalice/policy.json. You can also explicitly set this value to In order to ease transition, chalice will check for a .chalice/policy.json file when depoying to the dev stage. Support for .chalice/policy.json will be removed in future versions of chalice and users are encouraged to switch to the stage specific .chalice/policy-<stage-name>.json files.

See the Chalice Stages doc for more details on the new chalice stages feature.

Note, the AWS resource names it creates now have the form ``<app-name>-<stage-name>``, e.g. ``myapp-dev``, ``myapp-prod``.

We recommend using the new stage specific resource names. However, If you would like to use the existing resource names for a specific stage, you can create a .chalice/deployed.json file that specifies the existing values:

  "dev": {
    "backend": "api",
    "api_handler_arn": "lambda-function-arn",
    "api_handler_name": "lambda-function-name",
    "rest_api_id": "your-rest-api-id",
    "api_gateway_stage": "dev",
    "region": "your region (e.g us-west-2)",
    "chalice_version": "0.7.0",

This file is discussed in the next section.

Deployed Values

In version 0.7.0, the way deployed values are stored and retrieved has changed. In prior versions, only the lambda_arn was saved, and its value was written to the .chalice/config.json file. Any of other deployed values that were needed (for example the API Gateway rest API id) was dynamically queried by assuming the resource names matches the app name. In this version of chalice, a separate .chalice/deployed.json file is written on every deployement which contains all the resources that have been created. While this should be a transparent change, you may noticed issues if you run commands such as chalice url and chalice logs without first deploying. To fix this issue, run chalice deploy and version 0.7.0 of chalice so a .chalice/deployed.json will be created for you.

Authorizer Changes

The ``authorizer_id`` and ``authorization_type`` args are no longer supported in ``@app.route(…)`` calls.

They have been replaced with an authorizer_name parameter and an app.define_authorizer method.

This version changed the internals of how an API gateway REST API is created. Prior to 0.7.0, the AWS SDK for Python was used to make the appropriate service API calls to API gateway include create_rest_api and put_method / put_method_response for each route. In version 0.7.0, this internal mechanism was changed to instead generate a swagger document. The rest api is then created or updated by calling import_rest_api or put_rest_api and providing the swagger document. This simplifies the internals and also unifies the code base for the newly added chalice package command (which uses a swagger document internally). One consequence of this change is that the entire REST API must be defined in the swagger document. With the previous authorizer_id parameter, you would create/deploy a rest api, create your authorizer, and then provide that authorizer_id in your @app.route calls. Now they must be defined all at once in the app.py file:

app = chalice.Chalice(app_name='demo')

@app.route('/auth-required', authorizer_name='MyUserPool')
def foo():
    return {}



This version changed how the internals of how API gateway resources are created by chalice. The integration type changed from AWS to AWS_PROXY. This was to enable additional functionality, notable to allows users to provide non-JSON HTTP responses and inject arbitrary headers to the HTTP responses. While this change to the internals is primarily internal, there are several user-visible changes.

  • Uncaught exceptions with app.debug = False (the default value) will result in a more generic InternalServerError error. The previous behavior was to return a ChaliceViewError.

  • When you enabled debug mode via app.debug = True, the HTTP response will contain the python stack trace as the entire request body. This is to improve the readability of stack traces. For example:

    $ http https://endpoint/dev/
    HTTP/1.1 500 Internal Server Error
    Content-Length: 358
    Content-Type: text/plain
    Traceback (most recent call last):
      File "/var/task/chalice/app.py", line 286, in __call__
        response = view_function(*function_args)
      File "/var/task/app.py", line 12, in index
        return a()
      File "/var/task/app.py", line 16, in a
        return b()
      File "/var/task/app.py", line 19, in b
        raise ValueError("Hello, error!")
    ValueError: Hello, error!
  • Content type validation now has error responses that match the same error response format used for other chalice built in responses. Chalice was previously relying on API gateway to perform the content type validation. As a result of the AWS_PROXY work, this logic has moved into the chalice handler and now has a consistent error response:

    $ http https://endpoint/dev/ 'Content-Type: text/plain'
    HTTP/1.1 415 Unsupported Media Type
    Content-Type: application/json
        "Code": "UnsupportedMediaType",
        "Message": "Unsupported media type: text/plain"
  • The keys in the app.current_request.to_dict() now match the casing used by the AWS_PPROXY lambda integration, which are lowerCamelCased. This method is primarily intended for introspection purposes.

Frequently Asked Questions →