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
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:
setup/installation.md:
# Installation Details here.Running lychee on the file:
What was tried
--exclude '^/': Does not work. The exclude filter applies after URL resolution, but lychee errors out during resolution itself.--scheme https --scheme http --scheme file: Same problem. Scheme filtering happens after resolution.--base-urlwith--exclude: Transforms all links, including the relative file links, so the exclude pattern ends up filtering everything.Lookahead is not supported by the regex engine, so there is no way to exclude only the non-
.mdlinks.--root-dir /tmp/fake-rootwith--exclude '^file:///tmp/fake-root': This resolves root-relative links tofile:///tmp/fake-root/dashboard, which can then be excluded. However, relative file links like./setup/installation.mdalso get resolved underfile://and end up excluded too.Expected behavior
There should be a way to skip root-relative links without affecting other links. A few possible approaches:
--excludeto match against the raw link as extracted from the source, before URL resolution, so that--exclude '^/'would work.--ignore-unresolvableor--skip-unresolvablethat treats resolution failures as excluded rather than errors.--schemeor similar filtering to run before resolution so that links without a scheme can be dropped early.Environment