Skip to content

No clean way to exclude root-relative links when checking local files #2125

@Qwarctick

Description

@Qwarctick

When checking local Markdown or HTML files that contain a mix of root-relative links (e.g. /servers, /admin/settings) and relative file links (e.g. ./administration/ldap_configuration.md), there is no way to selectively ignore the root-relative links while still checking the relative file links.

Root-relative links are common in documentation that references application routes rather than other documentation pages. These links are not meant to be checked by lychee since they point to a live application behind authentication.

The core issue is that lychee fails during URL resolution for root-relative paths before any filtering (--exclude, --scheme) can take effect.

Reproduction

Given two files:

getting_started.md:

# Getting Started

See the [installation guide](./setup/installation.md) for details.

Go to [dashboard](/dashboard) in the application.

Check the [project settings](/projects/settings) for configuration.

setup/installation.md:

# Installation

Details here.

Running lychee on the file:

$ lychee getting_started.md
[ERROR] Cannot convert path '/dashboard' to a URI: To resolve root-relative links in local files, provide a root dir
[ERROR] Cannot convert path '/projects/settings' to a URI: To resolve root-relative links in local files, provide a root dir

What was tried

--exclude '^/': Does not work. The exclude filter applies after URL resolution, but lychee errors out during resolution itself.

$ lychee getting_started.md --exclude '^/'
[ERROR] Cannot convert path '/dashboard' to a URI [...]

--scheme https --scheme http --scheme file: Same problem. Scheme filtering happens after resolution.

$ lychee getting_started.md --scheme https --scheme http --scheme file
[ERROR] Cannot convert path '/dashboard' to a URI [...]

--base-url with --exclude: Transforms all links, including the relative file links, so the exclude pattern ends up filtering everything.

$ lychee getting_started.md --base-url "https://app.local" --exclude '^https://app\.local/(?!.*\.md)'
Error: look-around, including look-ahead and look-behind, is not supported

Lookahead is not supported by the regex engine, so there is no way to exclude only the non-.md links.

--root-dir /tmp/fake-root with --exclude '^file:///tmp/fake-root': This resolves root-relative links to file:///tmp/fake-root/dashboard, which can then be excluded. However, relative file links like ./setup/installation.md also get resolved under file:// and end up excluded too.

$ mkdir -p /tmp/fake-root
$ lychee getting_started.md --root-dir /tmp/fake-root --exclude '^file://'
🔍 10 Total ✅ 0 OK 🚫 0 Errors 👻 10 Excluded

Expected behavior

There should be a way to skip root-relative links without affecting other links. A few possible approaches:

  • Allow --exclude to match against the raw link as extracted from the source, before URL resolution, so that --exclude '^/' would work.
  • Add an option like --ignore-unresolvable or --skip-unresolvable that treats resolution failures as excluded rather than errors.
  • Allow --scheme or similar filtering to run before resolution so that links without a scheme can be dropped early.

Environment

  • lychee version: lychee 0.23.0
  • Input format: Markdown
  • OS: Ubuntu 24.04

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions