oxc-project/oxc · warning

`{role}` role is missing required aria props {props}.

Error message

`{role}` role is missing required aria props {props}.

What it means

This is the `jsx_a11y/role-has-required-aria-props` rule in oxlint. It fires when an element has a `role` but is missing one or more ARIA properties that the ARIA spec requires for that role — e.g. `checkbox` requires `aria-checked`, `slider` requires `aria-valuemin`/`aria-valuemax`/`aria-valuenow`, `heading` requires `aria-level`. Without them, assistive tech announces an incomplete widget.

Source

Thrown at crates/oxc_linter/src/rules/jsx_a11y/role_has_required_aria_props.rs:14

use oxc_ast::{
    AstKind,
    ast::{JSXAttributeItem, JSXAttributeValue},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use itertools::Itertools;

use crate::{AstNode, context::LintContext, rule::Rule, utils::has_jsx_prop_ignore_case};

fn role_has_required_aria_props_diagnostic(span: Span, role: &str, props: &str) -> OxcDiagnostic {
    OxcDiagnostic::warn(format!("`{role}` role is missing required aria props {props}."))
        .with_help(format!("Add missing aria props {props} to the element with `{role}` role."))
        .and_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct RoleHasRequiredAriaProps;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Enforces that elements with ARIA roles must have all required attributes
    /// for that role.
    ///
    /// ### Why is this bad?
    ///
    /// Certain ARIA roles require specific attributes to express necessary
    /// semantics for assistive technology.
    ///

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Add every required `aria-*` prop named in the diagnostic message, bound to real state.
  2. Prefer the native element (`<input type="checkbox">`) which manages required semantics itself.
  3. Double-check dynamic bindings — a conditional `aria-checked={undefined}` still counts as missing.

Example fix

// before
<span role="checkbox" tabIndex={0} aria-labelledby="lbl">Subscribe</span>

// after
<span role="checkbox" tabIndex={0} aria-checked={subscribed} aria-labelledby="lbl">Subscribe</span>
Defensive patterns

Strategy: validation

Validate before calling

npx oxlint --jsx-a11y/role-has-required-aria-props src/

Type guard

// Before rendering a role-based widget, assert its required props exist:
const hasRequiredAria = (role: string, props: Record<string, unknown>) => {
  const table: Record<string, string[]> = {
    checkbox: ['aria-checked'],
    slider: ['aria-valuemin', 'aria-valuemax', 'aria-valuenow'],
    heading: ['aria-level'],
  };
  return (table[role] ?? []).every((k) => props[k] !== undefined);
};

Prevention

When it happens

Trigger: A JSX opening element with a literal `role` attribute (found via `has_jsx_prop_ignore_case`) whose role, looked up in the embedded ARIA role->required-props table, has required properties, and at least one of those `aria-*` props is absent from the same element.

Common situations: Hand-rolled widgets: `role="checkbox"` without `aria-checked`, `role="progressbar"` without `aria-valuenow`, `role="heading"` without `aria-level`; copying example markup that omitted state attributes; refactors that dropped props during component extraction.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/fda5bf266fb0a79e. Report an issue: GitHub.