# eslint jsx-a11y no-redundant-roles error - how to fix it

## TL;DR

Delete the redundant role: role button on a button element, role navigation on a nav element, and friends add nothing. The element's native semantics already do the job. One line of why: redundant roles are harmless today but they rot, the day someone changes the element and forgets the role, the two disagree.

## The error, verbatim

```text
/app/src/components/Nav.jsx
  4:5  error  The element nav has an implicit ARIA role of navigation. Defining this explicitly is redundant  jsx-a11y/no-redundant-roles

```

## Fix it step by step

### Step 1: Reproduce on one file

```bash
npx eslint src/components/Nav.jsx --rule '{"jsx-a11y/no-redundant-roles": "error"}'
```

Expected: ESLint prints the no-redundant-roles error.

### Step 2: Find every redundant role

```bash
npx eslint src | rg 'no-redundant-roles' | head -20
```

Expected: Full list of elements carrying their own implicit role.

### Step 3: Delete the redundant roles

```bash
rg -n 'role=.button|role=.navigation|role=.main' src --glob '*.{jsx,tsx,html}' | head -20
```

Expected: Shows the usual suspects to clean up.

### Step 4: Re-lint

```bash
npx eslint src | rg -c 'no-redundant-roles' || echo 0
```

Expected: Prints 0. Native semantics now do the work with no duplication.

### Step 5: Enforce it in CI

```bash
npx eslint src --max-warnings 0 | tail -3
```

Expected: Clean output; add the lint command to CI with max-warnings 0 so the violation cannot come back.

## When to use this skill

- Your linter output names this exact jsx-a11y / a11y rule
- You want the violation fixed at author time so it never reaches axe or CI
- You are adding the rule to a shared eslint config and need the fix pattern

## When NOT to use this skill

- The failure comes from axe-core or lighthouse at runtime, not from lint
- You plan to disable the rule project-wide, this skill shows the fix, not the escape hatch

## Compatibility

eslint-plugin-jsx-a11y 6.7+ with eslint 8 or 9. Also flags redundant roles on elements like img (role img) and headings. Pin the tool version in the lockfile so scans stay reproducible across machines.

## Variant phrasings

### element has implicit aria role defining explicitly is redundant

The default message, same fix.

### jsx-a11y redundant role button

The classic: role button on an actual button element.

### the rule fires in the editor too

With the eslint extension installed, the same error appears inline while typing; the fix is identical.

## Why it happens

Authors add explicit roles defensively (role button on button) or copy them from examples without realizing the element already exposes that role. The rule maps elements to their implicit ARIA semantics and flags exact matches. It is a hygiene rule: redundant roles do not break anything today, but they double the maintenance surface and confuse future readers about intent. Linter rules catch the violation at author time, which is cheaper than any runtime fix. When this rule fires across many files, fix the shared component and mention it in team onboarding so new code does not reintroduce it.

## Edge cases

- The rule has an allowRedundantRoles option for teams that want explicit roles as documentation, but deleting is cleaner.
- role presentation on an img IS redundant and flagged, use alt="" on img elements instead.
- Custom elements have no implicit role, so explicit roles on them never trigger this rule.
- After fixing, run the whole lint suite once; a11y rules interact and one fix can surface the next violation.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_vt4yNmonxHhTqdbEnM1V6Q
