Skip to content
Latchkey

GitHub Actions "npm publish 403 to GitHub Packages" (scope)

Publishing an npm package to GitHub Packages requires the package name to be scoped to the owner, the registry configured to npm.pkg.github.com, and packages: write on the token. A scope or registry mismatch yields a 403.

What this error means

npm publish returns a 403 forbidden against npm.pkg.github.com even though authentication appeared to succeed.

github-actions
npm error code E403
npm error 403 Forbidden - PUT https://npm.pkg.github.com/@owner%2fpkg - permission_denied

Common causes

Package not scoped to the owner

GitHub Packages requires @owner/name scoping that matches the repository owner.

Missing packages: write or registry config

The job lacks packages: write, or .npmrc/setup-node did not point the scope at npm.pkg.github.com.

How to fix it

Fix scope, registry, and permission

  1. Scope the package name as @owner/name in package.json.
  2. Configure setup-node with the registry and scope, and grant packages: write.
  3. Authenticate with NODE_AUTH_TOKEN set to GITHUB_TOKEN.
.github/workflows/publish.yml
  publish:
    permissions:
      packages: write
      contents: read
    steps:
      - uses: actions/setup-node@v4
        with:
          registry-url: https://npm.pkg.github.com
          scope: '@owner'
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

How to prevent it

  • Keep the package scope aligned with the repository owner.
  • Configure the registry-url and scope via setup-node so .npmrc auth is generated correctly.

Frequently asked questions

What causes ""403" publishing to GitHub Packages"?
GitHub Packages requires @owner/name scoping that matches the repository owner.
How do I fix "403" publishing to GitHub Packages?
Fix scope, registry, and permission

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card