GitHub Actions to AWS: "Could not load credentials from any providers"
aws-actions/configure-aws-credentials found nothing to sign in with. When it gets neither a role it can assume with OIDC nor access keys, it falls back to the credentials of the machine, and a GitHub-hosted runner has none. Most often the role ARN or the keys were in the workflow but reached the action as an empty string: GitHub turns a secret it does not give to the run into "" and reports no error.
What it looks like
Retry validateCredentials: reached max retries (12); giving up. Error: Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers
The action tries 12 times with growing waits before it gives up (helpers.ts), so the step takes a while to fail. retry-max-attempts: 1 makes it fail at once while you look for the reason.
Which of the two cases
Open the step in the log and look above the retries.
- The line "It looks like you might be trying to authenticate with OIDC. Did you mean to set the
id-tokenpermission?" is there: the action logs it only whenrole-to-assumehas a value and the job has no OIDC token (index.ts). The role arrived; the permission is missing (6). - That line is not there, and the step's
with:list in the log has norole-to-assume(or noaws-access-key-id): the value was empty. In aws-durable-execution-docs (#301), konica/agent-tutor (#278) and saayam-for-all/ai (#215), the failed step's input list had no such line at all. Sections 1 to 4 are the usual reasons.
1. A pull request from a fork
GitHub's documentation: "With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is triggered from a forked repository." That covers the closed event too: in saayam-for-all/ai a deploy job that ran when a fork's pull request was merged failed this way, and the push to the branch that the merge makes has the secrets, so the deploy belongs on the push (#215). rotel-lambda-extension skips its AWS steps for fork pull requests (#99):
- uses: aws-actions/configure-aws-credentials@v6
if: ${{ github.event.pull_request.head.repo.fork != true }}
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1
2. Dependabot
GitHub's documentation: "When a Dependabot event triggers a workflow, the only secrets available to the workflow are Dependabot secrets. GitHub Actions secrets are not available." Dependabot's pull requests failed this way in NASA-IMPACT/veda-backend (#682) and shiptrack-modern (#61). Either store the value as a Dependabot secret with the same name, which the documentation suggests for workflows that both run, or skip the AWS steps with github.actor != 'dependabot[bot]', which shiptrack-modern chose so that Dependabot gets no AWS access.
3. The secret is not where the expression looks
- An environment secret reaches only jobs that use the environment. The documentation: "These secrets are only available to workflow jobs that use the environment." Add
environment: production(your environment's name) to the job. - The secret does not exist under that name. In aws-durable-execution-docs a check of the secret names found neither a repository secret
BEDROCK_ROLE_ARNnor any secret in the job's environment (#301). Names are listed under Settings > Secrets and variables > Actions, or withgh secret listandgh secret list --env NAME. - The ARN is stored as a variable, not a secret.
secrets.AWS_DEPLOY_ROLE_ARNis empty when the value is invars.AWS_DEPLOY_ROLE_ARN. verifypass reads either:${{ secrets.AWS_DEPLOY_ROLE_ARN || vars.AWS_DEPLOY_ROLE_ARN }}(#4).
4. A reusable workflow the secret was not passed to
A called workflow gets only the secrets its caller passes, even when its own job uses the environment that holds the secret. The documentation: "The caller workflow must still pass the secret", and "If the caller workflow doesn't pass an environment secret, the secret resolves to an empty string in the reusable workflow. The workflow run doesn't show an error." konica/agent-tutor's first deploy stopped here; it added secrets: inherit to the six calling jobs (#278).
# the caller
jobs:
deploy:
uses: ./.github/workflows/deploy.yml
secrets: inherit
# deploy.yml
on:
workflow_call:
secrets:
AWS_ROLE_ARN:
required: true
required: true makes the run fail when the caller does not pass the secret. It does not check that the secret has a value.
5. Stop on the empty value instead
Secrets cannot be used in if: directly; the documentation suggests a job-level environment variable. A step before the action then says what is wrong in one line, or the AWS steps can skip with if: env.AWS_ROLE_ARN != '':
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
env:
AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }}
steps:
- if: env.AWS_ROLE_ARN == ''
run: |
echo "::error::AWS_ROLE_ARN is empty in this run (fork, Dependabot, environment or caller)"
exit 1
- uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: ${{ env.AWS_ROLE_ARN }}
aws-region: us-east-1
6. The role is there but the job has no id-token: write
Without the permission the job gets no OIDC token, so the action does not try OIDC and ends at the same message. Add id-token: write. Job-level permissions: replace the workflow's, so a job that sets its own needs it too, and in a chain of reusable workflows permissions "can only be maintained or reduced" (the documentation), so the calling job needs it as well. When the token is there and AWS refuses it, the error becomes "Not authorized to perform sts:AssumeRoleWithWebIdentity": GitHub Actions OIDC to AWS.
7. Self-hosted runners
With no role and no keys, the action uses whatever the machine provides through the AWS SDK's default chain: environment variables, the ~/.aws files, container credentials (ECS, EKS, CodeBuild) and the instance metadata (CredentialsClient.ts). On a self-hosted runner this message means none of them answered for the runner's process. The action's README describes runners on CodeBuild and EKS, and role-chaining: true to assume another role from the machine's own.
Telling it apart
- "Credentials could not be loaded, please check your action inputs:" followed by AWS's own reason, such as "The security token included in the request is invalid": the keys reached the action and AWS rejected them. The action checks them with
GetCallerIdentityand puts AWS's message after the same opening. - "'aws-secret-access-key' must be provided if 'aws-access-key-id' is provided": only one of the two key secrets was empty.
- "Could not assume role with OIDC: Not authorized to perform sts:AssumeRoleWithWebIdentity": the token arrived and the role's trust policy did not match it (the OIDC page).
See failed jobs from IntelliJ IDEA
Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).
GitHub and GitHub Actions are trademarks of GitHub, Inc.; AWS is a trademark of Amazon.com, Inc. or its affiliates; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc., Amazon or JetBrains.
More: "Not authorized to perform sts:AssumeRoleWithWebIdentity" · npm publish "ENEEDAUTH" · "Resource not accessible by integration" · GitHub Actions plugins for IntelliJ IDEA compared · 日本語