# MD080 - Heading anchors must be unique
Aliases: `heading-anchor-collision`
**Opt-in:** disabled by default. Enable explicitly (e.g. add `MD080` to your
config's enabled rules) because the collision is functional under platform
auto-suffixing and flagging it changes established lint output.
## What this rule does
Flags two or more headings whose generated URL-safe anchor (slug) is identical.
The anchor is computed with the configured anchor style; an explicit
`{#custom-id}` takes precedence over the generated slug.
This is deliberately distinct from two neighbouring rules:
- **[MD024](md024.md)** flags duplicate heading *text*. It misses distinct
texts that slugify to the same anchor (`Setup & Run` vs `Setup Run`,
`C++` vs `C`).
- **[MD051](md051.md)** flags *broken* fragment references. MD080 flags
*ambiguous* fragment targets: the link resolves, but not unambiguously.
## Why this matters
A `[text](#slug)` link, and the virtual-page identifier some viewers derive
from an H1/H2 title, can only resolve to the *first* heading that produced a
given slug. GitHub and MkDocs paper over the collision by auto-suffixing the
later anchor (`slug-1`), which is functional but surprising: a hand-written
`#slug` link that meant the second heading silently lands on the first.
## Configuration
| `anchor-style` | string | `github` | Slug algorithm: `github`, `kramdown-gfm`, `kramdown`, `python-markdown`. When unset, follows the active flavor. |
| `levels` | array of int | `[1, 2, 3, 4, 5, 6]` | Heading levels whose anchors must be unique. Set to `[1, 2]` to check only page-identifier titles. |
```toml
[MD080]
# Slug algorithm: "github", "kramdown-gfm", "kramdown", or "python-markdown".
anchor-style = "github"
# Heading levels whose anchors must be unique. Use [1, 2] for page ids only.
levels = [1, 2, 3, 4, 5, 6]
```
## Examples
### Correct
```markdown
# Setup
## Configuration
## Usage
```
### Incorrect
```markdown
# Setup & Run
## Setup Run
```
Both headings slug to the same GitHub anchor, so `#setup--run` is ambiguous.
```markdown
# Intro
## Intro
```
Same text at different levels still produces one shared `#intro` anchor.
## Automatic fixes
None. Renaming a heading - and every link that targets it - is a semantic
decision the linter must not make automatically.
## Related rules
- [MD024 - Multiple headings with the same content](md024.md)
- [MD051 - Link fragments should reference valid headings](md051.md)