#21619·checkstyle

Competing archive and filename redirects for legacy release-notes links

Author: abhinav-phiCreated Sep 16, 2026Updated Sep 17, 2026

Summary

Follow-up requested by @romani in merged PR #21573.

While validating that PR, @smita1078 reported that a valid legacy release-notes link reached its archive on production but reached the renamed release-notes index on the generated site report instead. The website JavaScript contains two independent redirect handlers that can select different destinations for the same legacy URL.

This report tracks that redirect interaction separately from the version-component guard fixed by #21571 / #21573. It concerns the documentation website, not a Java Checkstyle check; a Java input file, check configuration, and CLI audit are not applicable.

Reported behavior and reproduction URLs

The validation report is in the discussion on #21573. The site report was generated from PR head 74d6ce95d20728135ef53f6847a06b8b0f6e9a80; the PR subsequently merged as f444f28260361492b70eb34ceba59cfdbddb0061.

To compare the reported behavior, open each legacy URL directly in a browser and inspect the final path and fragment:

Input Result reported during PR validation
Production: releasenotes.html#Release_6.0 release-notes-old-6-0-7-8.html#Release_6.0 — the expected archive
Site report: releasenotes.html#Release_6.0 release-notes.html rather than the archive
Production: releasenotes.html#Release_6 release-notes-old-6-0-7-8.html#Release_6 — the incomplete-version bug addressed by #21573
Site report: releasenotes.html#Release_6 release-notes.html rather than an archive

The valid #Release_6.0 case is the focus of this issue. The incomplete #Release_6 case is included to distinguish the merged guard fix from the remaining redirect interaction.

These are the reviewer's observations from validation, not a claim that every browser or every subsequent visit will reproduce the same destinations. Production may change after deployment, and the browser/version and cache conditions were not recorded in the original report. The rename handler preserves the fragment in its destination; a browser reproduction should record the complete final URL as well as the path.

Relevant code

Both handlers below are present in the merged source, src/site/resources/js/checkstyle.js.

1. Archive redirect on DOMContentLoaded

Source at the merge commit, lines 20–49

This handler processes /releasenotes.html when the fragment starts with #Release_ and the current document does not already contain that anchor. After checking the version components, it selects an archive. For #Release_6.0, it calls:

javascript
window.location.replace(`./release-notes-old-6-0-7-8.html${url.hash}`);

2. Filename redirect on load

Source at the merge commit, lines 51–115

A separate handler processes pages whose title starts with Redirecting. Its map includes:

javascript
"releasenotes.html": "release-notes.html",

It constructs another destination and requests navigation:

javascript
const newUrl = `./${redirectMap[oldHtmlFile]}${urlObj.hash}`;
window.location.replace(newUrl);

Both fetched legacy pages had the title Redirecting – checkstyle. For a valid archived release, the first handler selects the archive, while the second can select the renamed index if the original document reaches its load handler before it is replaced. There is no explicit coordination between these redirect decisions.

Evidence and limits of the diagnosis

During the PR investigation:

  • Comparing the served production and site-report checkstyle.js files showed only the guard-line difference: !versionParts.length >= 2 versus versionParts.length < 2.
  • For #Release_6.0, versionParts.length is 2. Neither version of that condition returns early, so the guard change does not change archive selection for this input.
  • A Node DOM-stub harness executing the served scripts, with DOMContentLoaded followed by load, recorded an archive navigation request followed by a renamed-index navigation request for valid archived versions such as #Release_7.8 and #Release_8.20, with both script versions.

The harness demonstrates the conflicting navigation requests when both handlers execute. It does not simulate browser navigation cancellation or establish which request commits in a real browser. Event/navigation timing is a plausible explanation for the reported discrepancy, but it still needs browser-level confirmation. The differing sizes of the fetched pages do not, by themselves, prove that page size caused the different outcomes.

Expected behavior

A valid legacy archive link such as releasenotes.html#Release_6.0 should reliably reach release-notes-old-6-0-7-8.html#Release_6.0. A generic filename redirect should not supersede an archive destination selected for that same URL.

Other existing navigation behavior should remain intact:

  • Legacy links without an archive destination should retain the normal filename-rename fallback where appropriate.
  • Incomplete versions such as #Release_6 must not regain an archive redirect that #21573 removed.
  • An existing release anchor in the current document must not be incorrectly routed to an archive.
  • Unrelated documentation filename redirects should continue to work.

Suggested direction and validation

Coordinate the archive and filename-rename decisions so that the intended destination is selected once, with explicit precedence for a matching archive. The implementation could centralize destination selection or otherwise prevent the generic redirect from superseding an archive request.

Simply skipping the rename for every #Release_ fragment would be too broad: malformed, current, and otherwise unmatched versions still need defined fallback behavior. Moving handlers between events alone would also need verification that the competing navigation requests are actually eliminated.

Suggested regression coverage:

Input category Behavior to verify
Valid archived releases, including 6.0, 7.8, 8.20, and 10.26 Correct archive and unchanged fragment; no competing rename request
Incomplete version, e.g. #Release_6 No archive redirect; appropriate fallback remains available
No fragment Normal releasenotes.html filename redirect
Anchor already present in the document No erroneous archive selection
Version outside the archive ranges Defined fallback, not an arbitrary archive
Other renamed documentation pages Existing redirects remain unchanged

Browser validation should record browser/version, final URL, and relevant cache/network conditions. Testing both production-like and generated-site pages would help establish that archive navigation no longer depends on the observed deployment difference.

Related work and scope

  • #21573: merged version-component guard fix and the discussion requesting this follow-up.
  • #21571: original precedence bug; not being reopened here.
  • #21398: broader proposal to centralize historical redirects and generate compatibility pages.

This issue is the narrower user-visible release-notes routing problem. It does not require the architectural migration proposed in #21398, although that work may provide the eventual solution. If addressed there, the archive-precedence and fallback cases above should be covered explicitly.