Skip to content
Latchkey

GitHub Actions Cannot Pull Private GHCR Image - packages: read

A pull of a private GHCR image (as a base image, container job, or service) is denied because the GITHUB_TOKEN lacks packages: read or the package does not grant access to the workflow repository.

What this error means

A docker pull, container job, or service using a private ghcr.io image fails with a denied/unauthorized error while public images pull fine.

Actions log
Error response from daemon: denied
# pulling ghcr.io/org/base:1.0 with a token lacking packages: read,
# or the package has not granted this repo access

Common causes

Token lacks packages: read

Reading a private package over GHCR needs packages: read on the workflow token. A token without it cannot pull the image.

Package access not granted to the repo

A private GHCR package must explicitly grant the consuming repository (or org) access; otherwise even a correctly scoped token is denied.

How to fix it

Grant packages: read and log in

Add packages: read and authenticate to GHCR before pulling.

.github/workflows/ci.yml
permissions:
  contents: read
  packages: read
steps:
  - uses: docker/login-action@v3
    with:
      registry: ghcr.io
      username: ${{ github.actor }}
      password: ${{ secrets.GITHUB_TOKEN }}
  - run: docker pull ghcr.io/org/base:1.0

Grant the package to the repo

  1. In the package settings, add the consuming repository with read access.
  2. For container jobs/services, provide container.credentials with a token that can read the image.
  3. Use a PAT with read:packages when pulling across owners the GITHUB_TOKEN cannot reach.

How to prevent it

  • Declare packages: read on jobs that pull private images.
  • Grant each private package access to the repos that consume it.
  • Authenticate to GHCR before pulling private images.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →