elastic/elasticsearch · critical · IllegalStateException

Changelog directory contains changes that will be wiped out

Error message

Changelog directory contains changes that will be wiped out by this task:
{changelogDirectory}
{output}

What it means

Thrown by BundleChangelogsTask.checkoutChangelogs before running `git rm -rf` on the changelog directory. It runs `git status --porcelain <changelogDir>`; if any output is produced (modified, staged, or untracked files exist), the task aborts to avoid silently destroying uncommitted changelog work during the checkout/restore sequence.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BundleChangelogsTask.java:225

            entries.sort(changelogEntryComparator());

            ChangelogBundle bundle = new ChangelogBundle(version, finalize, Instant.now().toString(), entries);

            yamlMapper.writeValue(new File("docs/release-notes/changelog-bundles/" + version + ".yml"), bundle);
        } finally {
            if (didCheckoutChangelogs) {
                gitWrapper.runCommand("git", "restore", "-s@", "-SW", "--", changelogDirectory.get().toString());
            }
        }
    }

    private void checkoutChangelogs(GitWrapper gitWrapper, String upstream, String ref) {
        gitWrapper.updateRemote(upstream);

        // If the changelog directory contains modified/new files, we should error out instead of wiping them out silently
        var output = gitWrapper.runCommand("git", "status", "--porcelain", changelogDirectory.get().toString()).trim();
        if (output.isEmpty() == false) {
            throw new IllegalStateException(
                "Changelog directory contains changes that will be wiped out by this task:\n" + changelogDirectory.get() + "\n" + output
            );
        }

        gitWrapper.runCommand("rm", "-rf", changelogDirectory.get().toString());
        var refSpec = upstream + "/" + ref;
        if (ref.contains("upstream/")) {
            refSpec = ref.replace("upstream/", upstream + "/");
        } else if (ref.matches("^[0-9a-f]+$")) {
            refSpec = ref;
        }
        gitWrapper.runCommand("git", "checkout", refSpec, "--", changelogDirectory.get().toString());
    }

    private void addChangelogsFromRef(GitWrapper gitWrapper, String upstream, String ref) {
        var refSpec = upstream + "/" + ref;
        if (ref.contains("upstream/")) {
            refSpec = ref.replace("upstream/", upstream + "/");

View on GitHub (pinned to db6a809a66)

Solutions

  1. Commit, stash, or revert local changes in the changelog directory before running bundleChangelogs (git stash or git checkout -- <changelogDir>).
  2. If the changes are intentional and should be preserved, move them out of the directory or commit to a branch first.
  3. Re-run the task once `git status --porcelain <changelogDir>` is empty.
  4. If the dirty state is from a prior failed run, inspect and clean it deliberately rather than letting the task wipe it.

Example fix

// before: dirty changelog dir
$ git status --porcelain changelogs/
?? changelogs/heads-up/foo.yaml
$ ./gradlew bundleChangelogs --branch 8.x  // throws
// after: stash or commit first
$ git stash push -- changelogs/
$ ./gradlew bundleChangelogs --branch 8.x
Defensive patterns

Strategy: validation

Validate before calling

String dirty = gitRun("status", "--porcelain", changelogDir.toString()).trim();
if (dirty.isEmpty() == false) {
    throw new IllegalStateException("Commit or stash changelog changes first:\n" + dirty);
}

Prevention

When it happens

Trigger: The task is about to checkout changelog YAMLs from a ref into the local changelog directory, which involves `git rm -rf <dir>` followed by `git checkout <ref> -- <dir>`. If the directory currently has uncommitted changes, those would be wiped, so the porcelain check fails fast.

Common situations: A developer has local in-progress changelog edits when running the bundling task; an untracked new changelog file was added but not committed; a previous bundling run left the directory dirty; merge conflict resolution left changelog files modified.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/a1151ca9cf78ae42. Report an issue: GitHub.