# Bad value “” for attribute “aria-activedescendant” on element “input”: An ID must not be the empty string.

> Canonical HTML version: https://rocketvalidator.com/html-validation/bad-value-for-attribute-aria-activedescendant-on-element-input-an-id-must-not-be-the-empty-string
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

The `aria-activedescendant` attribute tells assistive technologies which child element within a composite widget — such as a combobox, listbox, or autocomplete dropdown — is currently "active" or focused. Instead of moving actual DOM focus to each option, the parent element (like an `input`) retains focus while `aria-activedescendant` points to the visually highlighted option by referencing its `id`. This allows screen readers to announce the active option without disrupting keyboard interaction on the input.

When `aria-activedescendant` is set to an empty string (`""`), it creates an invalid state. The HTML and ARIA specifications require that any ID reference attribute either contains a valid, non-empty ID token or is omitted altogether. An empty string is not a valid ID, so the W3C validator flags this as an error: **Bad value "" for attribute "aria-activedescendant" on element "input": An ID must not be the empty string.**

This problem commonly occurs in JavaScript-driven widgets where `aria-activedescendant` is cleared by setting it to `""` when no option is highlighted — for example, when a dropdown closes or the user clears their selection. While the developer's intent is correct (indicating that nothing is active), the implementation is wrong.

### Why this matters

- **Accessibility**: Screen readers may behave unpredictably when encountering an empty ID reference. Some may silently ignore it, while others may announce errors or fail to convey widget state correctly.
- **Standards compliance**: The ARIA specification explicitly requires ID reference values to be non-empty strings that match an existing element's `id`.
- **Browser consistency**: Browsers handle invalid ARIA attributes inconsistently, which can lead to different experiences across platforms and assistive technologies.

### How to fix it

1. **Remove the attribute** when no descendant is active. Use `removeAttribute('aria-activedescendant')` in JavaScript instead of setting it to an empty string.
2. **Set a valid ID** when a descendant becomes active, pointing to the `id` of the currently highlighted or selected option.
3. **Never render the attribute in HTML** with an empty value. If your framework or templating engine conditionally renders attributes, ensure it omits the attribute entirely rather than outputting `aria-activedescendant=""`.

## Examples

### Incorrect: empty string value

This triggers the W3C validation error because the attribute value is an empty string.

```html
<input type="text" role="combobox" aria-activedescendant="" />
```

### Correct: attribute omitted when no option is active

When nothing is active, simply leave the attribute off.

```html
<input type="text" role="combobox" aria-expanded="false" />
```

### Correct: valid ID reference when an option is active

When a user highlights an option, set `aria-activedescendant` to that option's `id`.

```html
<div role="combobox">
  <input
    type="text"
    role="combobox"
    aria-expanded="true"
    aria-controls="suggestions"
    aria-activedescendant="option2" />
  <ul id="suggestions" role="listbox">
    <li id="option1" role="option">Apple</li>
    <li id="option2" role="option" aria-selected="true">Banana</li>
    <li id="option3" role="option">Cherry</li>
  </ul>
</div>
```

### Correct: managing the attribute dynamically with JavaScript

The key fix in JavaScript is using `removeAttribute` instead of setting the value to an empty string.

```html
<div role="combobox">
  <input
    id="search"
    type="text"
    role="combobox"
    aria-expanded="true"
    aria-controls="results" />
  <ul id="results" role="listbox">
    <li id="result1" role="option">First result</li>
    <li id="result2" role="option">Second result</li>
  </ul>
</div>
<script>
  const input = document.getElementById('search');

  function setActiveOption(optionId) {
    if (optionId) {
      input.setAttribute('aria-activedescendant', optionId);
    } else {
      // Remove the attribute instead of setting it to ""
      input.removeAttribute('aria-activedescendant');
    }
  }
</script>
```

In summary, always ensure `aria-activedescendant` either points to a real, non-empty `id` or is removed from the element. Never set it to an empty string.
