Checkout of private repo failed - GITHUB_TOKEN lacks cross-repo read
actions/checkout fails with 'Could not read Username for https://github.com'
Focused incident mode — strips away everything but this runbook.
Symptoms
- actions/checkout fails with 'Could not read Username for https://github.com'
- fatal: could not read Username for 'https://github.com': no such device or address
- Workflow fails at checkout step when accessing a second private repository
GitHub's default GITHUB_TOKEN is scoped to the current repository only. For cross-repo checkout, a fine-grained or classic PAT with repo scope is mandatory.
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
Checkout step configuration
cat .github/workflows/<file>.yml | grep -A8 'uses: actions/checkout'Token scope on the event
gh api repos/<OWNER/REPO>/actions/runs/<RUN_ID> --jq '.head_branch'
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- Checkout uses the default token without specifying a PAT
- The target repository is in a different org or under a different owner
Confirm before fixing
gh api repos/<OTHER_OWNER>/<OTHER_REPO> --jq '.full_name'Test if the repo is reachable with the default token
Fix
cat .github/workflows/<file>.yml | sed 's|uses: actions/checkout@v4|uses: actions/checkout@v4\n with:\n token: ${{ secrets.CROSS_REPO_PAT }}|'Pass a PAT with repo scope to the checkout action
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
gh run view <RUN_ID> --log-failed | grep -B5 'Could not read Username'Identify the exact checkout that fails
cat .github/workflows/<file>.yml | grep -A10 'uses: actions/checkout'Check if a token is passed to checkout
gh api repos/<OTHER_OWNER>/<OTHER_REPO> --jq '.visibility'Test access with the current token
gh secret set CROSS_REPO_PAT -b '<PAT_WITH_REPO_SCOPE>'Store a PAT with repo scope for cross-repo access
Prevention
- Always pass a PAT via token: to actions/checkout when accessing other private repos.
- Create fine-grained PATs scoped only to the specific repos needed.
- Store the PAT as a repository secret and rotate it before expiry.
- Use GitHub App installation tokens for organization-wide cross-repo access.
Related runbooks
Same stack, same failure family — worth a skim.
Docker push to ghcr.io fails with 'denied: permission_denied' or '403 Forbidden'
Error: Resource not accessible by integration
Step logs show empty string where a secret should be
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.