If the environment variable AWS_PROFILE is set to an empty string, then boto3.client raises an exception. It does so even if client credentials are explicitly specified by keyword arguments or other means.
Expected behavior
Setting AWS_PROFILE= should be treated the same way as having AWS_PROFILE unset (i.e., it should fall back to other methods for determining credentials.)
There's no rule or standard saying that you need to treat an empty environment variable the same as one that is undefined - it's just common practice and good if you want to avoid surprising people. In the case of boto3, it's impossible to have a profile with an empty name, so it doesn't make sense to try to search for one.
Current behavior
If AWS_PROFILE is set to an empty string, then boto3.client('s3') raises botocore.exceptions.ProfileNotFound, apparently regardless of what other arguments or environment variables are defined.
Reproduction Steps
rm -rf ~/.aws
pip install boto3
python3
>>> import os
>>> [os.environ.pop(v) for v in os.environ if v.startswith('AWS')]
>>> import boto3
This succeeds (and returns a client with no credentials):
>>> boto3.client('s3')
<botocore.client.S3 object at 0x7f6dfb706fd0>
This succeeds (and returns a client with credentials):
>>> boto3.client('s3', aws_access_key_id='AKIAZZ', aws_secret_access_key='xx')
<botocore.client.S3 object at 0x7f6dfb5abfd0>
This ought to succeed (and return a client with no credentials):
>>> os.environ['AWS_PROFILE'] = ''
>>> boto3.client('s3')
...
botocore.exceptions.ProfileNotFound: The config profile () could not be found
This ought to succeed (and return a client with credentials):
>>> os.environ['AWS_PROFILE'] = ''
>>> boto3.client('s3', aws_access_key_id='AKIAZZ', aws_secret_access_key='xx')
...
botocore.exceptions.ProfileNotFound: The config profile () could not be found
Possible Solution
In botocore.session.Session.get_scoped_config:
--- session.py.orig
+++ session.py
@@ -413,7 +413,7 @@
# If a profile is not explicitly set return the default
# profile config or an empty config dict if we don't have
# a default profile.
- if profile_name is None:
+ if not profile_name:
return profile_map.get('default', {})
elif profile_name not in profile_map:
# Otherwise if they specified a profile, it has to
Additional Information/Context
For one example of where this issue is an annoyance: Python's unittest.mock.patch.dict provides an easy way to temporarily override environment variables for a unit test, but it doesn't let you undefine variables.
Describe the bug
If the environment variable
AWS_PROFILE
is set to an empty string, thenboto3.client
raises an exception. It does so even if client credentials are explicitly specified by keyword arguments or other means.Expected behavior
Setting
AWS_PROFILE=
should be treated the same way as havingAWS_PROFILE
unset (i.e., it should fall back to other methods for determining credentials.)There's no rule or standard saying that you need to treat an empty environment variable the same as one that is undefined - it's just common practice and good if you want to avoid surprising people. In the case of boto3, it's impossible to have a profile with an empty name, so it doesn't make sense to try to search for one.
Current behavior
If
AWS_PROFILE
is set to an empty string, thenboto3.client('s3')
raisesbotocore.exceptions.ProfileNotFound
, apparently regardless of what other arguments or environment variables are defined.Reproduction Steps
This succeeds (and returns a client with no credentials):
This succeeds (and returns a client with credentials):
This ought to succeed (and return a client with no credentials):
This ought to succeed (and return a client with credentials):
Possible Solution
In
botocore.session.Session.get_scoped_config
:Additional Information/Context
For one example of where this issue is an annoyance: Python's
unittest.mock.patch.dict
provides an easy way to temporarily override environment variables for a unit test, but it doesn't let you undefine variables.SDK version used
boto3 1.34.31 botocore 1.34.31
Environment details (OS name and version, etc.)
Debian 12, Python 3.11