Non-atomic overflow write leaves release-notes.md missing, and every later run fails with "Failed to find file"

Open
#2,950 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 2 days

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
github, node.js, typescript

Research direction

Start with FilePullRequestOverflowHandler.handleOverflow in the overflow write path and parseOverflow, which reads release-notes.md from the notes branch. Trace how createFileOnNewBranch updates the branch before writing the file, then inspect the tests for overflow parsing and file creation. Done means a failed write no longer leaves later runs unable to recover; the issue suggests atomic writes or treating a missing overflow file as recoverable.

Written by the indexing model from the issue text.

Description

priority: p3 type: bug
Environment details
  • OS: GitHub Actions ubuntu-24.04 runner
  • Node.js version: node24 (the action's runtime)
  • npm version: n/a (the bundled action)
  • release-please version: 17.6.0, via googleapis/release-please-action v5.0.0. The same code is on main and in v17.11.2.
Summary

When a release PR's body exceeds 65,536 characters, FilePullRequestOverflowHandler.handleOverflow stores the notes in release-notes.md on <head branch>--release-notes. It does this through GitHubApi.createFileOnNewBranch (src/github-api.ts), which makes two separate API calls:

  1. forkBranch force-updates the notes branch to the default branch's SHA (git.updateRef with force: true).
  2. repos.createOrUpdateFileContents commits release-notes.md onto it.

If the second call fails (for example on a GitHub 5xx), the notes branch is left on a plain default-branch commit with no release-notes.md. The release PR's body still holds the overflow link to that file.

After that, every run fails, and release-please can't recover on its own:

  • Manifest.createPullRequests → findOpenReleasePullRequests → parseOverflow calls getFileContentsOnBranch('release-notes.md', <notes branch>). That throws FileNotFoundError, and nothing catches it.
  • This happens before createOrUpdatePullRequest → updatePullRequest → handleOverflow, the step that would rewrite the file.
  • findMergedReleasePullRequests also calls parseOverflow. So if the release PR is merged in this state, building the release fails the same way and nothing is tagged.

The run that hit the 5xx failed right after the branch update, with:

release-please failed: Server Error

Every later run fails with:

release-please failed: Failed to find file: release-notes.md

Deleting the notes branch doesn't help, because parseOverflow still follows the link in the body and fails before anything recreates the branch. The workaround is to point the notes branch back at the previous "Saving release notes" commit by hand, or to edit the release PR's body.

Steps to reproduce
  1. Have an open release PR whose notes exceed 65,536 characters, so its body is the overflow message and the notes live in release-notes.md on the --release-notes branch.
  2. Make createOrUpdateFileContents fail after forkBranch has succeeded. A GitHub 5xx does this in practice. To simulate it, force-update the --release-notes branch to the default branch's head, which has no release-notes.md.
  3. Run release-please again. It fails with Failed to find file: release-notes.md on this run and on every run after it.
Suggested fix

Either of these would avoid the stuck state:

  • Make the write atomic. Create the blob, tree and commit with the git data API, parented on the default branch's SHA, then move the notes branch to that commit with a single updateRef. A failure at any step then leaves the previous notes in place.
  • Treat a missing overflow file as recoverable. In parseOverflow, catch FileNotFoundError, log a warning and return a body that is known to differ from the candidate's. The open PR is then still matched by its head branch, and updatePullRequest → handleOverflow rewrites the file on the same run.
Dominant language
TypeScript
Stars
7.8k
Forks
621
Avg merge
1d 23h
Merged PRs (30d)
8

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from googleapis/release-please

All issues in googleapis/release-please

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.