hermes - ✅(Solved) Fix Bug: batch_runner final checkpoint duplicates completed_prompts entries [2 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

batch_runner.py deduplicates completed_prompts incrementally with completed_prompts_set, but the final checkpoint rebuild appends each batch's completed_prompts back onto the already-deduplicated list.

This can produce duplicate prompt IDs in the final checkpoint.

Root Cause

batch_runner.py deduplicates completed_prompts incrementally with completed_prompts_set, but the final checkpoint rebuild appends each batch's completed_prompts back onto the already-deduplicated list.

This can produce duplicate prompt IDs in the final checkpoint.

Fix Action

Fixed

PR fix notes

PR #13321: fix(batch_runner): don't re-append per-batch completed_prompts to the final checkpoint

Description (problem / solution / changelog)

Summary

Closes #13285.

batch_runner.py's incremental checkpoint path maintains completed_prompts_set as a deduplicated set of every completed prompt ID (lines 925-939, written to disk as sorted(completed_prompts_set) at line 941). The final-aggregation path, however, did:

all_completed_prompts = list(completed_prompts_set)
for batch_result in results:
    all_completed_prompts.extend(batch_result.get('completed_prompts', []))

…which re-appends every prompt that's already in the set — so the final checkpoint contains each completed ID twice. Checkpoint consumers expect completed_prompts to be the set of completed items; duplicates inflate counts and complicate resume/progress logic.

The fix

Drop the extend loop, write sorted(completed_prompts_set) directly. Matches the shape already used by the incremental write at line 941 and keeps output deterministic for easier diff/review of checkpoint files.

Diff

-        # Aggregate all batch statistics and update checkpoint
-        all_completed_prompts = list(completed_prompts_set)
+        # Aggregate all batch statistics and update checkpoint.
+        # NB: completed_prompts_set is already maintained as a dedup'd
+        # set of every completed prompt ID; we must NOT extend this list
+        # again from each batch result below, or the final checkpoint
+        # will contain duplicates.  See #13285.
         total_reasoning_stats = {...}

         for batch_result in results:
-            # Add newly completed prompts
-            all_completed_prompts.extend(batch_result.get("completed_prompts", []))
-
             # Aggregate tool stats
             ...
...
-        # Save final checkpoint (best-effort; incremental writes already happened)
+        # Save final checkpoint (best-effort; incremental writes already happened).
+        # Use the already-deduplicated set, sorted for deterministic output,
+        # matching the format written by the incremental checkpoint path above.
         try:
-            checkpoint_data["completed_prompts"] = all_completed_prompts
+            checkpoint_data["completed_prompts"] = sorted(completed_prompts_set)
             self._save_checkpoint(checkpoint_data, lock=checkpoint_lock)

1 file changed, +11, −8.

Verification

Using the reporter's minimal repro shape:

completed_prompts_set = {'p0'}
results = [{'completed_prompts': ['p0']}]
# Before: list(completed_prompts_set) + extend -> ['p0', 'p0']
# After:  sorted(completed_prompts_set)         -> ['p0']
  • python3 -m py_compile batch_runner.py → clean.
  • Confirmed all_completed_prompts is no longer referenced anywhere else in the file (grep returns nothing).
  • Incremental checkpoint behavior at lines 925-941 is unchanged.

Linked Issue

  • Closes #13285

Changed files

  • batch_runner.py (modified, +11/-8)

PR #13324: fix(batch): dedupe final checkpoint completions

Description (problem / solution / changelog)

Summary

  • Fixes #13285
  • Deduplicates completed prompt IDs when writing the final batch checkpoint
  • Keeps incremental checkpoint recovery behavior intact while preventing final aggregation from re-adding the same prompt IDs

Root Cause

The parent process updated completed_prompts_set during incremental checkpoint writes, then initialized final aggregation from that same set and extended it again with each batch result. That made final completed_prompts contain duplicates.

Tests

  • uv run --python 3.11 --extra dev pytest tests/test_batch_runner_checkpoint.py -q (14 passed)
  • git diff --check -- batch_runner.py tests/test_batch_runner_checkpoint.py

Changed files

  • batch_runner.py (modified, +12/-5)
  • tests/test_batch_runner_checkpoint.py (modified, +15/-1)

Code Example

completed_prompts_set = set()
results = []
result = {'batch_num': 0, 'completed_prompts': ['p0']}
completed_prompts_set.update(result['completed_prompts'])
results.append(result)
all_completed_prompts = list(completed_prompts_set)
for batch_result in results:
    all_completed_prompts.extend(batch_result.get('completed_prompts', []))
print(all_completed_prompts)

---

['p0', 'p0']
RAW_BUFFERClick to expand / collapse

Summary

batch_runner.py deduplicates completed_prompts incrementally with completed_prompts_set, but the final checkpoint rebuild appends each batch's completed_prompts back onto the already-deduplicated list.

This can produce duplicate prompt IDs in the final checkpoint.

Affected files

  • batch_runner.py:925-939
  • batch_runner.py:949-977

Why this is a bug

Checkpoint consumers expect completed_prompts to represent the set of completed items. Duplicates can inflate counts and complicate resume/progress logic.

Minimal reproduction

The relevant logic reduces to:

completed_prompts_set = set()
results = []
result = {'batch_num': 0, 'completed_prompts': ['p0']}
completed_prompts_set.update(result['completed_prompts'])
results.append(result)
all_completed_prompts = list(completed_prompts_set)
for batch_result in results:
    all_completed_prompts.extend(batch_result.get('completed_prompts', []))
print(all_completed_prompts)

Observed output:

['p0', 'p0']

Expected behavior

The final checkpoint should preserve unique completed prompt IDs.

Actual behavior

The final write can contain duplicates even when the incremental checkpoint state was deduplicated.

Suggested investigation direction

Use the already-maintained completed_prompts_set (or re-deduplicate before the final save) instead of extending the set-derived list with each batch result again.

extent analysis

TL;DR

The most likely fix is to re-deduplicate the completed_prompts list before the final save by using the completed_prompts_set or converting the list to a set to remove duplicates.

Guidance

  • Review the logic in batch_runner.py lines 925-939 and 949-977 to understand how completed_prompts and completed_prompts_set are updated and used.
  • Consider using the completed_prompts_set directly for the final checkpoint instead of extending the list with each batch result.
  • Before the final save, convert the all_completed_prompts list to a set to remove duplicates, then convert it back to a list if necessary.
  • Verify that the fix works by checking the output of the minimal reproduction code and ensuring that the final checkpoint contains unique completed prompt IDs.

Example

all_completed_prompts = list(completed_prompts_set)  # Use the set directly
# or
all_completed_prompts = list(set(all_completed_prompts))  # Re-deduplicate the list

Notes

This fix assumes that the order of the completed prompts does not matter. If the order is important, a different approach may be needed to preserve the order while removing duplicates.

Recommendation

Apply the workaround by re-deduplicating the completed_prompts list before the final save, as this is a straightforward fix that can be implemented without waiting for a potential future version update.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The final checkpoint should preserve unique completed prompt IDs.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix Bug: batch_runner final checkpoint duplicates completed_prompts entries [2 pull requests]