boto/boto3 · critical · NoCredentialsError

Unable to locate credentials

Error message

Unable to locate credentials

What it means

`NoCredentialsError` at this site is raised specifically when the caller passes `aws_account_id=` to `boto3.Session(...)` (or `setup_default_session`) without also supplying real credentials (`aws_access_key_id` + `aws_secret_access_key`). boto3 cannot derive credentials from an account id alone, so it refuses rather than silently proceeding as anonymous. The shared message text ('Unable to locate credentials') is the standard botocore NoCredentialsError wording.

Solutions

  1. Provide real credentials alongside the account id: `boto3.Session(aws_access_key_id=..., aws_secret_access_key=..., aws_account_id=...)`.
  2. Configure a named profile (`~/.aws/credentials` or `AWS_PROFILE`) that contains the keys, then pass only `aws_account_id`.
  3. In an AWS runtime (EC2/Lambda/ECS/Fargate), attach an IAM role so credentials resolve automatically; then `aws_account_id` is optional.
  4. If you genuinely want anonymous access for a public resource, drop `aws_account_id` (it forces the credentials check path).

Example fix

# before
sess = boto3.Session(aws_account_id='123456789012')  # NoCredentialsError

# after (option A: explicit keys)
sess = boto3.Session(
    aws_access_key_id=AK, aws_secret_access_key=SK, aws_account_id='123456789012',
)
# after (option B: rely on a configured profile / role, drop account_id)
sess = boto3.Session(profile_name='prod')
Defensive patterns

Strategy: validation

Validate before calling

def build_session(aws_account_id=None, **creds):
    has_real = creds.get('aws_access_key_id') and creds.get('aws_secret_access_key')
    if aws_account_id and not has_real and not os.environ.get('AWS_PROFILE'):
        raise ValueError('aws_account_id provided without any credentials')
    return boto3.Session(aws_account_id=aws_account_id, **creds)

Type guard

def account_id_has_credentials(aws_account_id, access_key, secret_key, session_token) -> bool:
    if aws_account_id is None:
        return True
    return bool(access_key and secret_key) or bool(session_token)

Try / catch

from botocore.exceptions import NoCredentialsError
try:
    sess = boto3.Session(aws_account_id=acct)
except NoCredentialsError:
    sess = boto3.Session()  # fall back to env/IMDS profile without account_id

Prevention

When it happens

Trigger: Constructing a Session with `boto3.Session(aws_account_id='123456789012')` but no access key/secret and no resolvable credentials in the environment (no profile, no env vars, no IMDS). Also when only `aws_session_token` is provided without key/secret.

Common situations: Newer boto3 feature: `aws_account_id` was added to disambiguate accounts, but developers mistakenly treat it as a credential; running on a host without AWS credentials configured while attempting to pin an account id; CI where only an account id is injected as an env var.

Related errors


AI-assisted analysis of boto/boto3@6e10b029c1 (2026-08-11). Data as JSON: /api/errors/3c082f39ef1914e1. Report an issue: GitHub.

Appendix: source

Thrown at boto3/session.py:93

                self._session.user_agent_extra += f" {botocore_info}"
            else:
                self._session.user_agent_extra = botocore_info
            self._session.user_agent_name = 'Boto3'
            self._session.user_agent_version = boto3.__version__

        if profile_name is not None:
            self._session.set_config_variable('profile', profile_name)

        credentials_kwargs = {
            "aws_access_key_id": aws_access_key_id,
            "aws_secret_access_key": aws_secret_access_key,
            "aws_session_token": aws_session_token,
            "aws_account_id": aws_account_id,
        }

        if any(credentials_kwargs.values()):
            if self._account_id_set_without_credentials(**credentials_kwargs):
                raise NoCredentialsError()

            if aws_account_id is None:
                del credentials_kwargs["aws_account_id"]

            self._session.set_credentials(*credentials_kwargs.values())

        if region_name is not None:
            self._session.set_config_variable('region', region_name)

        self.resource_factory = ResourceFactory(
            self._session.get_component('event_emitter')
        )
        self._setup_loader()
        self._register_default_handlers()

    def __repr__(self):
        return '{}(region_name={})'.format(
            self.__class__.__name__,

View on GitHub (pinned to 6e10b029c1)