Skip to content
WCAG 4.1.2 Name, Role, Value

How to fix: ARIA references must point to unique IDs

When an id used by an ARIA attribute appears more than once, assistive tech resolves the wrong element and the relationship breaks.

The fix

Make sure any id referenced by an ARIA attribute is unique on the page.

Who this affects

aria-labelledby, aria-describedby and aria-controls resolve to the first element in the document with that id, so a duplicate quietly points assistive technology at the wrong node. A screen-reader user filling in the third row of a repeated form hears the error message belonging to the first row, or a description for a field they are not on, with no clue that anything is wrong. The general duplicate-id rules were deprecated when WCAG 2.2 removed 4.1.1 Parsing; this variant stayed because the reference really does resolve to the wrong element, and axe reports it under 4.1.2 Name, Role, Value at Level A.

Before and after

Fails
<input aria-describedby="hint"> … <p id="hint">…</p><p id="hint">…</p>
Passes
<input aria-describedby="hint-email"> … <p id="hint-email">…</p>

Where this usually comes from

  • A field component hard-codes id="error" or id="description" and the page renders that component once per row.
  • A server-side loop renders the same partial for every record without adding the record key to the ids inside it.
  • The navigation is output twice, once for desktop and once for the mobile drawer, duplicating every id in it.
  • A dialog is rendered both in place and in a portal at the end of <body> while the original copy stays in the DOM.
  • A React component uses a constant id string rather than useId, so a second instance on the same page collides with the first.

Checking it yourself

Paste const ids=[...document.querySelectorAll('[id]')].map(e=>e.id); ids.filter((v,i)=>ids.indexOf(v)!==i) into the console. Anything it returns that is referenced by aria-labelledby, aria-describedby, aria-controls or a label's for attribute is a genuine break. Then select the affected control in Chrome devtools and read the Accessibility pane, which shows the computed name and description and the element each was taken from, usually the first copy near the top of the page.

A scanner finds this one automatically. What it cannot judge, and how the score is built, is on how we test.

Related fixes

Check your site for this issue

Scan any page free against WCAG 2.2 AA and get every automatically detected issue with its fix.

Scanning a page needs no account. The checks run on axe-core.

← All fix guides