( Robust / WCAG 4.1.2 )

ARIA attribute is not valid for the current role value

SeriousLevel AWCAG 4.1.2 — Name, Role, Value

What is this issue?

An ARIA attribute is present on an element and is a genuinely real, spec-recognized attribute for that element’s role, but the WAI-ARIA specification only defines it as meaningful when a further condition also holds, and that condition isn’t met. The clearest example: aria-expanded and aria-level on a table <tr> are only valid when the table’s role is treegrid, a role built specifically to represent an expandable, hierarchical grid. On a plain <table> or a role="grid", those same attributes have no defined behavior at all.

This is a narrower failure than an attribute simply being unsupported by a role outright. aria-expanded genuinely belongs to the row-level vocabulary a treegrid uses: the problem is the surrounding structure hasn’t actually adopted the role that makes the attribute meaningful.

Why does this matter?

When an attribute is used outside the condition the specification requires for it, the result isn’t a clean fallback: it’s undefined behavior. Different screen readers and browsers can interpret the same markup differently, which means a component that appears to work correctly in one testing setup can behave completely differently for a real user on a different combination of browser and assistive technology.

This matters most for components that look identical on screen regardless of the underlying role. A file manager rendered as nested folders and files inside a plain <table>, using aria-expanded and aria-level to hint at hierarchy without the table actually being a treegrid, might render pixel-perfect nested rows, but a screen reader has no reliable way to announce that hierarchy, because the attributes it would use to do so were never given the structural context they require.

Who is affected?

  • Screen reader users: get an unreliable or missing announcement of hierarchy, expand/collapse state, or nesting level, since the attributes meant to convey that structure aren’t recognized outside their required condition, and different screen readers may fail differently or silently.

What users experience

Priyanka uses NVDA on Windows to manage files in a web-based cloud storage admin panel. The file list is a plain <table> with folders and files as rows, using aria-level and aria-expanded on each <tr> to hint at folder nesting, but the table never adopted role="treegrid", the structural role those attributes require. NVDA reads each row as a flat table row with no announced level or expand state at all, so Priyanka can’t tell which files are nested inside which folders just by listening; she has to open every folder in sequence and track the visual indentation herself, something a sighted user reads instantly from the layout.

How do I fix it?

Give the container the role the attribute’s condition actually requires: in the row-hierarchy case, set role="treegrid" on the table, role="row" on each <tr>, and role="gridcell" on each cell, so aria-expanded and aria-level land inside a structure that gives them defined meaning. This works because the specification only defines the interaction and announcement behavior for these attributes within a treegrid’s row/cell vocabulary; matching that structure is what makes the browser and screen reader interpret the attributes correctly.

If restructuring the component to a full treegrid isn’t practical, remove the conditional attributes instead of leaving them in an invalid context. An unlabeled flat table with no false hierarchy signal is more predictable for a screen reader user than a table that gestures at structure it doesn’t actually support: a missing feature is more honest than a broken one.

Code Examples

Before
<table>
  <tr>
    <td>Documents</td>
  </tr>
  <tr aria-level="2" aria-expanded="true">
    <td>Q3 Report.pdf</td>
  </tr>
</table>
After
<!-- Row-level attributes now sit inside a treegrid, where they are valid -->
<table role="treegrid" aria-label="File browser">
  <tr role="row">
    <td role="gridcell">Documents</td>
  </tr>
  <tr role="row" aria-level="2" aria-expanded="true">
    <td role="gridcell">Q3 Report.pdf</td>
  </tr>
</table>

The fix adds role="treegrid" to the table and role="row"/role="gridcell" to its rows and cells, which gives aria-level and aria-expanded the exact structural context the specification requires for them to mean anything. Without that surrounding treegrid role, the same attributes on the same <tr> elements were syntactically valid ARIA but semantically undefined: the fix isn’t adding new attributes, it’s giving the ones already there a role structure that makes them work.

Common Mistakes

Mistake: “The attribute is spelled correctly and is a real ARIA property, so it should work anywhere.” Being a real, correctly-spelled ARIA attribute is necessary but not sufficient: several attributes, aria-expanded and aria-level on rows chief among them, are only defined within a specific structural context. The same attribute that’s perfectly valid inside a treegrid has no defined behavior on a plain table row.

Mistake: “It renders fine in my screen reader, so the condition must not matter.” Undefined behavior doesn’t mean uniformly broken behavior; it means unpredictable behavior that can vary by screen reader, browser, and even version. Passing in one manual test only confirms that specific combination happened to do something reasonable with it, not that every combination will.

Mistake: “I’ll just remove role=‘treegrid’ because it sounds too complex for what I’m building.” Skipping the structural role doesn’t simplify the accessibility story; it just leaves the state attributes without the context that makes them meaningful, which is worse for a screen reader user than not attempting hierarchy signaling at all. If a treegrid genuinely doesn’t fit the component, remove the conditional attributes rather than leaving them stranded.

How RedFlag Detects This

Automated: axe-core rule, runs on every scan. RedFlag calls axe-core’s aria-conditional-attr rule as part of every scan, restricted to the WCAG 2.0/2.1/2.2 A and AA rule set. The rule checks attributes that the WAI-ARIA specification defines as valid only under a stated condition (such as row-level aria-expanded/aria-level requiring an ancestor with the treegrid role) and flags them when that condition isn’t met.

False negative: the rule confirms the structural condition is met; it can’t confirm the attribute’s value is being kept accurate as the component’s real state changes: a correctly-structured treegrid row can still announce the wrong expand/collapse state if the underlying script forgets to update aria-expanded on toggle. False positive: none typical for this check, since the required condition for each conditional attribute is explicitly defined in the specification and axe-core checks it directly. Manual step: confirm the restructured component’s keyboard and screen reader behavior actually matches a real treegrid’s expected interaction pattern, not just that the roles are technically present.

Manual Testing

  1. Open the page in Chrome or Firefox with NVDA or JAWS running.
  2. Navigate to the component using the attribute (a nested table, an expandable row, a hierarchical list) with the screen reader’s table or list navigation commands.
  3. Listen for the screen reader to announce level and expand/collapse state as you move between rows: a working treegrid announces something like “level 2, expanded” alongside each row’s content.
  4. If the screen reader announces rows as flat, with no level or expand state despite the visual hierarchy on screen, the attributes are likely present without the required structural condition.
  5. Open the browser’s accessibility inspector (Chrome DevTools → Elements → Accessibility pane) and confirm the table’s computed role is “tree grid,” not “table” or “grid”; a mismatch here confirms the condition isn’t met.

4.1.2 Name, Role, Value: Every interface component must expose its role, name, and current state reliably to assistive technology. An attribute used outside its required condition fails this criterion because its state can no longer be reliably interpreted, even though the attribute itself is syntactically valid.

ARIA role is invalid is a prerequisite this rule assumes is already correct: a genuinely invalid role produces a different, more foundational failure than a valid role missing its required condition.

ARIA attribute name is not valid and ARIA attribute has an invalid value cover the two simpler failure modes (a misspelled attribute name, or a malformed value) that commonly get confused with this rule’s more structural, context-dependent failure.

ARIA attribute is not allowed for this role covers attributes that are never valid on a role in any context, the unconditional version of this rule’s conditional failure.

ARIA element is missing a required parent role shares the same root cause of structural context: a role or attribute needing a specific surrounding structure that the markup doesn’t provide.

References

Frequently asked questions

How is a conditionally-valid attribute different from one that is simply not allowed?

An attribute the aria-allowed-attr check flags is never valid on that role, in any context. A conditionally-valid attribute is genuinely valid on the role, but only when a second condition is also true, such as another attribute holding a specific value or the element sitting inside a specific parent structure.

Does aria-checked on a row need a treegrid specifically, or does any table work?

It needs a treegrid specifically. A plain table or a grid without the treegrid role does not support row-level aria-expanded or aria-level, because those properties describe a hierarchical, expandable tree structure that a flat table or grid does not represent.

Can I just remove the conditional attribute if I do not want to restructure the component?

Yes, if the state or property it conveys is not actually needed. If a table row genuinely has no expand/collapse behavior, aria-expanded and aria-level should not be there at all: removing them is a valid fix, not just a workaround, since the attributes were never meaningful outside their required condition.

Are there other common examples of conditionally-valid ARIA attributes besides treegrid rows?

Yes. aria-checked is valid on role="option" only when the containing listbox has aria-multiselectable set, and aria-posinset/aria-setsize are only meaningful when an element's full set of siblings is not represented in the DOM, such as a virtualized or paginated list.

Does axe-core know the difference between a table and a treegrid automatically?

Yes. axe-core reads the resolved role of the ancestor container, whether set explicitly with role="treegrid" or left as an implicit table, and checks the attribute's validity against that specific ancestor role rather than assuming a fixed context.