ArchiveTool dump aborts on DELETED/INVALID catalog entries (missing the state filter that describe has)
Summary
ArchiveTool <archiveDir> dump throws IllegalArgumentException and aborts the entire run as soon as the catalog contains a recording in a non-VALID state (e.g. DELETED after AeronArchive.purgeRecording, or INVALID). describe, describe-all, and verify all tolerate non-valid entries, but dump hands every catalog entry straight to a RecordingReader, including ones whose segment files have already been deleted.
Because purged recordings remain in the catalog as DELETED tombstones until an offline compact, any long-running archive that rotates/purges recordings (e.g. snapshot rotation) accumulates such entries — making dump effectively unusable on it.
Affected versions: reproduced on 1.52.2; the code path is unchanged on master at time of writing.
Steps to reproduce
- Record a stream and stop it.
AeronArchive.purgeRecording(recordingId)(marks the catalog entryDELETEDand deletes its segments) — orArchiveTool <dir> mark-invalid <id>.ArchiveTool <dir> dump.
Actual
Recording 0
streamId: 100
stream length: 40296512
[RecordingDescriptorHeader](... state=DELETED ...)
[RecordingDescriptor](... recordingId=0 | startPosition=3523862336 | stopPosition=3564158848 ...)
Exception in thread "main" java.lang.IllegalArgumentException: length must be positive
at io.aeron.archive.RecordingReader.<init>(RecordingReader.java:86)
at io.aeron.archive.ArchiveTool.dump(ArchiveTool.java:1207)
at io.aeron.archive.ArchiveTool.lambda$dump$4(ArchiveTool.java:579)
at io.aeron.archive.Catalog.invokeEntryProcessor(Catalog.java:995)
at io.aeron.archive.Catalog.forEach(Catalog.java:511)
at io.aeron.archive.ArchiveTool.dump(ArchiveTool.java:578)
at io.aeron.archive.ArchiveTool.main(ArchiveTool.java:143)The first non-VALID entry aborts the whole dump; valid recordings later in the catalog are never reached.
Expected
dump skips (or notes and continues past) non-VALID recordings the way describe does, so valid recordings are still dumped.
Root cause
dump (ArchiveTool.java:578) iterates catalog.forEach(...) with no state check, whereas describe guards with if (hd.state() == VALID). For a DELETED/INVALID entry the segments are gone, so the per-recording dump → new RecordingReader(...) throws IllegalArgumentException: length must be positive (RecordingReader.java:86).
Suggested fix
Skip entries whose headerDecoder.state() != VALID in the dump forEach lambda (mirroring describe); optionally add a dump-all variant if dumping invalid entries is ever wanted.
Source: aeron-io/aeron