Skip to content

Link checker flakes on healthy sites, so it reports instead of gating #2789

Open

Description

@devantler

🤖 Generated by the Agentic Engineer

Evidence

The link checker reaches the public internet from a shared GitHub runner, and as a hard gate it
reddens pull requests for other people's transient network conditions. Measured across four
consecutive runs on #2776:

Run Failing links
3 https://fluxcd.io/ — connection reset
4 none
5 https://kubernetes.io/docs/reference/access-authn-authz/authentication/ and one more kubernetes.io path — connection errors

Every one of those hosts answered 200 from a laptop within seconds of the failure. Run 4 added
--max-retries 5, --retry-wait-time 3 and --max-concurrency 8 and run 5 still flaked, so this is
not a tuning problem — it is what an internet-dependent check does on shared infrastructure.

#2776 therefore moves SPELL_LYCHEE into DISABLE_ERRORS_LINTERS: it keeps running and keeps
reporting every finding on every pull request, but does not fail the build.

Why not just ignore the hosts

Because the checker earns its keep. In this same pull request it found a genuinely dead link —
dexidp.io had moved a page under /docs/configuration/ — which was fixed rather than ignored. Adding
live sites to .lycheeignore would stop checking them for real, which is the opposite of what is
wanted.

What would make it gate again

Something that separates "this link is broken" from "this runner could not reach the internet just
now". Options worth weighing:

  • lychee's cache (--cache, with a max age) so a link verified recently is not re-fetched, which
    cuts both flake and runtime;
  • retrying only the failing set at the end of a run rather than inline;
  • treating connection-class errors as warnings and status-code errors as failures, if lychee can
    express that.

Acceptance criteria

  • Three consecutive runs on unchanged content produce no link failures.
  • A deliberately broken link still fails the build (verify by adding one, not by reasoning).
  • SPELL_LYCHEE is removed from DISABLE_ERRORS_LINTERS.

Rough size: small. Blocked by #2776.

Activity

  1. added theissue type on Jul 21, 2026
  2. moved this to 📥 Backlog in 🌊 Project Boardon Jul 21, 2026
  3. devantler commented on Sep 16, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Related: KSail is splitting the same class, for 5xx responses only

    devantler-tech/ksail#7083 (for ksail#6398) takes the "gate on correctness, report availability separately" split this issue describes, but only for HTTP 502/503/504 responses. Measured with lychee 0.24.2 against a local test server: lychee makes one request for a 503 and fails immediately, while a hung request is retried with backoff. So for a 5xx, no retry setting can help. The ksail change accepts those three codes in the gate (404, malformed URLs and 500 still fail) and adds a retried daily availability check for its own docs site.

    That does not cover what this issue measured here: connection resets and connection errors, which lychee does retry and which still flaked after retries were raised. Those remain open here. If platform later gates on lychee again, accepting 502..=504 is worth including, since it removes the one failure mode retries cannot reach.

  4. moved this from 📥 Backlog to 🧊 Icebox in 🌊 Project Boardon Oct 8, 2026
  5. devantler commented on Oct 25, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer (interactive Claude Code session)

    Blocked, 2026-10-25: the link checker does not run in this repository any more, so there is no gate to restore yet.

    lychee runs inside MegaLinter, and MegaLinter reaches this repository only through the organization's shared Go workflow. The organization rule requires that workflow only on repositories whose detected language is Go, and GitHub now detects this repository as Shell. The default branch's rules list no shared Go workflow, and no run of it appears among the 500 most recent workflow runs.

    Three green runs in a row cannot be shown while nothing runs the check. #4990 tracks the shared Go workflow not running here, and its outcome decides where a link check would live. The options recorded above (a lychee cache, accepting 502 to 504 as ksail#7083 does, re-checking only the failures) still apply once it runs again.

    Blocker: #4990.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    None yet

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions