🔧 Error Fixes
· 2 min read
Last updated on

GitHub Actions: Permission Denied — How to Fix It


Error: Process completed with exit code 128.
fatal: could not read Username for 'https://github.com': Permission denied

This error means your GitHub Actions workflow doesn’t have the right permissions to perform the operation — usually pushing to a repo, creating a PR, or accessing a private repository.

What causes this

GitHub Actions uses a GITHUB_TOKEN that’s automatically generated for each workflow run. By default, this token has limited permissions. You’ll hit this error when:

  • The workflow tries to push commits or tags but only has read access
  • You’re trying to access a different repository (the token is scoped to the current repo)
  • The repository’s default workflow permissions are set to read-only
  • You’re using actions/checkout without the right token for private submodules

Fix 1: Add permissions to your workflow

Explicitly declare the permissions your workflow needs at the job or workflow level:

name: Deploy
on: push

permissions:
  contents: write        # Push commits, create tags
  pull-requests: write   # Create/update PRs
  packages: write        # Push to GitHub Container Registry

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git push

Only request the permissions you actually need. Adding permissions at the top level restricts the token to only those scopes.

Fix 2: Change default repository permissions

If you don’t want to add permissions to every workflow file:

  1. Go to your repo → Settings → Actions → General
  2. Scroll to “Workflow permissions”
  3. Select “Read and write permissions”
  4. Save

This changes the default for all workflows in the repo. The explicit permissions block in a workflow file always overrides this default.

Fix 3: Use a Personal Access Token for cross-repo access

The default GITHUB_TOKEN only works for the current repository. To access other repos, use a PAT or a GitHub App token:

steps:
  - uses: actions/checkout@v4
    with:
      repository: your-org/other-repo
      token: ${{ secrets.PAT_TOKEN }}

Create the PAT at GitHub → Settings → Developer settings → Personal access tokens, and add it as a repository secret.

Fix 4: Fix submodule checkout

If your repo uses private submodules, the default token can’t access them:

steps:
  - uses: actions/checkout@v4
    with:
      submodules: recursive
      token: ${{ secrets.PAT_TOKEN }}  # PAT with access to submodule repos

How to prevent it

  • Always add an explicit permissions block to your workflows. It documents what the workflow needs and follows the principle of least privilege.
  • For organization repos, consider using a GitHub App instead of a PAT. App tokens are scoped, rotated automatically, and aren’t tied to a personal account.
  • Test permission changes in a branch first — a misconfigured permissions block can break existing workflows by restricting the token more than the default.
📘