A lambda failed to start with the error "cannot import name 'is_s3express_bucket' from 'botocore.utils'"

0

I recently encountered an issue with a newly deployed Lambda function running on Python 3.8 (version 3.8.v33). When attempting to execute boto3.client("s3") or boto3.resource("s3"), it throws an error stating: "cannot import name 'is_s3express_bucket' from 'botocore.utils'."

Interestingly, when I set up a new Lambda function through the AWS Console, this error does not occur. This leads me to believe the issue isn't with the code itself, as it seems to be conditionally reproducible.

Could anyone suggest approaches to isolate and identify the underlying cause of this issue?

Minimum reproducing code I think

import boto3
s3 = boto3.resource("s3")
# s3 = boto3.client("s3")  # Same as above

Reproduced environment

INIT_START Runtime Version: python:3.8.v33 Runtime Version ARN: arn:aws:lambda:ap-northeast-1::runtime:353a31d9fb2c7cac8474d278a6cf08824c7f87f698d61d1df2c128fc25a48d43

boto3.version='1.26.90' botocore.version='1.29.90'

(added) region=ap-northeast-1

But I can't find any differences between the succeeded lambda and the failed lambda.

What I have done

  • I saw the lambda run successfully at about 1:00 AM JST(+9:00)
  • I deployed the stack including the lambda at 8:00 AM JST, and then I found the lambda failed to start.
    • I modified the lambda from the console and tested it, and then the error was reproduced.
  • I deleted the stack and deployed again at 10:40 AM JST, and then the lambda still failed.
asked 5 months ago8384 views
3 Answers
0
Accepted Answer

We faced a similar issue, resolved by setting the version of both boto3 and botocore in requirements.txt and shipping as part of the vendor dependencies.

What I think is going on, the Lambda function's default/built-in/baked-in dependencies of boto3 and botocore are mismatched, such that boto3 is using latest version (1.33.2) but botocore is using a previous version (1.33.1).

I tested this hypothesis and was able to reproduce the issue:

(venv5) Braverman@Local ~/Repos/apply-api (set-boto-version-1.33.1) $ pip list | grep boto
boto3           1.33.2
botocore        1.33.1
(venv5) Braverman@Local ~/Repos/apply-api (set-boto-version-1.33.1) $ python
Python 3.8.3 (default, Jul  8 2020, 14:27:55) 
[Clang 11.0.3 (clang-1103.0.32.62)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import boto3
s3 = boto3.resource("s3")
>>> s3 = boto3.resource("s3")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
...
ImportError: cannot import name 'is_s3express_bucket' from 'botocore.utils' (/Users/steven.braverman/Repos/apply-api/venv5/lib/python3.8/site-packages/botocore/utils.py)

However, if I match up the environments, things run smoothly:

(venv5) Braverman@Local ~/Repos/apply-api (master) $ pip list | grep boto
boto3           1.33.2
botocore        1.33.2
>>> import boto3
s3 = boto3.resource("s3")
>>> s3 = boto3.resource("s3")
>>> 

It is interesting that the new version of Lambda you deployed is not facing this issue. Deploying the new lambda function must have triggered a pip install -U on the lambda function's dependencies, which seems to not occur for already existing lambda functions.

captain
answered 5 months ago
profile pictureAWS
EXPERT
reviewed 5 months ago
  • Thanks for your comment.

    What I think is going on, the Lambda function's default/built-in/baked-in dependencies of boto3 and botocore are mismatched, such that boto3 is using latest version (1.33.2) but botocore is using a previous version (1.33.1).

    I agree with your guess. Specifying versions of both boto3 and botocore will solve the problem. It would be nice if we could control the boto3 version, but we have removed boto3 and botocore from our SAM build due to lambda code size limitations.

    Note that the versions of boto3 and botocore were not the latest(1.26.90 and 1.29.90), and they were the same as another lambda that does not cause the error.

  • I tried to add the following to my requirements.txt, instead of specifying boto3 and botocore versions, and I got the lambda succeeded.

    s3transfer==0.8.0
    

    Because is_s3express_bucket is added in https://github.com/boto/s3transfer/commit/3b50c31bb608188cdfb0fc7fd8e8cd03b6b7b187

0

There seems to be something off with your versions. Where are you printing those versions from? What is odd is that the "s3express" method that is causing the exception is something that was added with the latest version of botocore/boto3 (on 2023.11.28) in version 1.33.2.

It would be strange that older versions of botocore/boto3 are complaining about "s3express" when "s3express" does not exist until 1.33.2 https://github.com/boto/botocore/commit/af4fdde1a2e053f3d9d9d91e7ad13167388528ce

captain
answered 5 months ago
  • boto3.version='1.26.90' botocore.version='1.29.90'

    I got the output from the following code in the lambda.

    import boto3
    import botocore
    print(f"{boto3.__version__=}")
    print(f"{botocore.__version__=}")

    The error seems to come from a sub package of boto3, s3transfer. It appears that this has started supporting s3express in 0.8.1. I tried to fix the version of s3transfer only, then it seems to work for me.

0

The answer above is correct. We also faced this issue because we were packing s3transfer from our local development environment with the Lambda function, while boto and botocore were coming from the Lambda environment.

The solution for us was to either use all of the libraries from the runtime (built-in) or package all of them with the function code. Went for the first one and it worked.

answered 5 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions