Skip to content

FocusScope crashes with single radio button in form #9569

@jtstothard

Description

@jtstothard

Provide a general summary of the issue here

FocusScope throws TypeError: (intermediate value)(intermediate value)(intermediate value) is not iterable when it contains a form with exactly one unchecked radio button.

The bug is in the isTabbableRadio function in @react-aria/focus. It assumes form.elements.namedItem() always returns a RadioNodeList, but per the DOM spec, it returns:

  • RadioNodeList (iterable) when there are 2+ elements with the same name
  • Element (NOT iterable) when there is exactly 1 element with that name
  • null when no elements match

🤔 Expected Behavior?

FocusScope should handle forms with a single radio button without crashing.

😯 Current Behavior

When a FocusScope contains a form with exactly one unchecked radio button, the following error is thrown:

TypeError: (intermediate value)(intermediate value)(intermediate value) is not iterable
    at isTabbableRadio (FocusScope.mjs:222:16)
    at Object.acceptNode (FocusScope.mjs:579:22)
    ...

The error occurs at line 306-307 in FocusScope.tsx:

let radioList = element.form?.elements?.namedItem(element.name) as RadioNodeList;
radios = [...(radioList ?? [])] as HTMLInputElement[];  // CRASHES here when radioList is Element

💁 Possible Solution

Check if namedItem() returns a single Element before spreading:

// Before (buggy)
let radioList = element.form?.elements?.namedItem(element.name) as RadioNodeList;
radios = [...(radioList ?? [])] as HTMLInputElement[];

// After (fixed)
let radioList = element.form?.elements?.namedItem(element.name);
if (radioList instanceof Element) {
  radios = [radioList as HTMLInputElement];
} else if (radioList) {
  radios = [...radioList] as HTMLInputElement[];
}

🔦 Context

Our application has a modal (using FocusScope) containing a form where users select from available options rendered as radio buttons. When only one option is available, the form renders a single radio button, which causes this crash.

This is a regression introduced in PR #8488 (merged 2025-07-09) which added the isTabbableRadio function.

🖥️ Steps to Reproduce

https://codesandbox.io/p/devbox/nice-benz-pyl67f?workspaceId=ws_Sdyx9f621KCtw6eyHa9hZK

  1. Create a component that uses FocusScope with contain prop
  2. Inside the FocusScope, add a form with exactly ONE unchecked radio button
  3. Render the component
  4. Error is thrown
import { FocusScope } from 'react-aria';

function BugRepro() {
  return (
    <FocusScope contain restoreFocus autoFocus>
      <div>
        <button>First button</button>
        <form>
          {/* Single radio button triggers the bug */}
          <input type="radio" name="option" value="only" />
          <label>Only Option</label>
        </form>
        <button>Second button</button>
      </div>
    </FocusScope>
  );
}

Version

  • react-aria: 3.45.0 - @react-aria/focus: 3.21.3

What browsers are you seeing the problem on?

Chrome, Other

If other, please specify.

All browsers - this is a DOM API behavior, not browser-specific

What operating system are you using?

macOS

🧢 Your Company/Team

No response

🕷 Tracking Issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggood first issueGood for newcomers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions