Skip to content
Latchkey

softprops/action-gh-release "Validation Failed: already_exists"

GitHub rejects the release create call with 422 "already_exists" when a release for the same tag is already published. The action tries to create rather than reuse.

What this error means

A release step fails with "Validation Failed" and a field error "already_exists" on tag_name.

github-actions
Error: Validation Failed: {"resource":"Release","code":"already_exists","field":"tag_name"}
##[error]Validation Failed

Diagnose it: what token do you actually have?

Permission failures in Actions are almost never about your repository settings alone. Three things combine: the default GITHUB_TOKEN permission set for the repo or organization, the permissions: block in the workflow, and whether the event is a fork pull request, which downgrades the token to read-only regardless of everything else.

.github/workflows/ci.yml
- name: Show the token scopes actually granted
  run: |
    curl -sI -H "Authorization: Bearer $GITHUB_TOKEN" \
      https://api.github.com/ | grep -i "^x-oauth-scopes\|^x-accepted"
    echo "event: ${{ github.event_name }}"
    echo "fork PR: ${{ github.event.pull_request.head.repo.fork }}"
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Common causes

Tag already has a release

A prior run or a manual release created the same tag, so creating again is a conflict.

Re-running a published tag

Re-running the job on an existing tag attempts to recreate the release instead of updating it.

How to fix it

Tie the release to a fresh tag, or allow updates

  1. Trigger the release on push of a new tag (on: push: tags) so each release maps to a unique tag.
  2. Or move/delete the stale tag and release before re-running.
  3. Re-run; the create call now succeeds.
.github/workflows/release.yml
on:
  push:
    tags: ['v*']
jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}

Grant the narrowest permission that works

Declaring a permissions: block switches the job from the repository default to exactly what you list, so an incomplete block is a common cause of a new failure right after someone tightened security. List every scope the job needs, not just the one that failed.

.github/workflows/ci.yml
permissions:
  contents: read        # checkout
  packages: write       # push to GHCR
  id-token: write       # OIDC to a cloud provider
  pull-requests: write  # comment on or label a PR
  checks: write         # publish check runs

How to prevent it

  • Drive releases from tag pushes so the tag is unique per release.
  • Avoid re-running release jobs against an already-published tag.

Frequently asked questions

What causes softprops/action-gh-release "Validation Failed: already_exists"?
There are 2 common causes: tag already has a release and re-running a published tag. A prior run or a manual release created the same tag, so creating again is a conflict.
How do I fix softprops/action-gh-release "Validation Failed: already_exists"?
Tie the release to a fresh tag, or allow updates. Trigger the release on push of a new tag (on: push: tags) so each release maps to a unique tag.
What does softprops/action-gh-release "Validation Failed: already_exists" actually mean?
A release step fails with "Validation Failed" and a field error "already_exists" on tag_name.
How do I stop softprops/action-gh-release "Validation Failed: already_exists" happening again?
Drive releases from tag pushes so the tag is unique per release. The prevention section lists 2 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card