vitest-dev/vitest · error · Error

input with type=checkbox or type=radio cannot be used with .

Error message

input with type=checkbox or type=radio cannot be used with .toHaveValue(). Use .toBeChecked() for type=checkbox or .toHaveFormValues() instead

What it means

Thrown by `toHaveValue` at toHaveValue.ts:27-33 when the received element is an `<input>` whose `type` is `checkbox` or `radio`. Checkboxes/radios don't have a single meaningful `.value`; the matcher would conflate the unchecked state with the value attribute, so Vitest refuses and points users to the correct matchers.

Source

Thrown at packages/browser/src/client/tester/expect/toHaveValue.ts:31

 * copies or substantial portions of the Software.
 */

import type { MatcherResult, MatcherState } from 'vitest'
import type { Locator } from '../locators'
import { arrayAsSetComparison, getElementFromUserInput, getMessage, getSingleElementValue, isInputElement } from './utils'

export default function toHaveValue(
  this: MatcherState,
  actual: Element | Locator,
  expectedValue?: string,
): MatcherResult {
  const htmlElement = getElementFromUserInput(actual, toHaveValue, this)

  if (
    isInputElement(htmlElement)
    && ['checkbox', 'radio'].includes(htmlElement.type)
  ) {
    throw new Error(
      'input with type=checkbox or type=radio cannot be used with .toHaveValue(). Use .toBeChecked() for type=checkbox or .toHaveFormValues() instead',
    )
  }

  const receivedValue = getSingleElementValue(htmlElement)
  const expectsValue = expectedValue !== undefined

  let expectedTypedValue = expectedValue
  let receivedTypedValue = receivedValue
  // eslint-disable-next-line eqeqeq
  if (expectedValue == receivedValue && expectedValue !== receivedValue) {
    expectedTypedValue = `${expectedValue} (${typeof expectedValue})`
    receivedTypedValue = `${receivedValue} (${typeof receivedValue})`
  }

  return {
    pass: expectsValue
      ? this.equals(receivedValue, expectedValue, [arrayAsSetComparison, ...this.customTesters])

View on GitHub (pinned to d568f8ce37)

Solutions

  1. For checkboxes use `toBeChecked()`/`toBeUnchecked()`.
  2. For forms containing checkboxes/radios use `toHaveFormValues({ groupName: expectedValueOrArray })`.
  3. If you really need the `value` attribute string, assert on the attribute: `expect(el).toHaveAttribute('value', 'on')`.

Example fix

// before
expect(page.getByRole('checkbox')).toHaveValue('on')

// after
expect(page.getByRole('checkbox')).toBeChecked()
// or, for the whole form:
expect(form).toHaveFormValues({ accept: true })
Defensive patterns

Strategy: validation

Validate before calling

function isCheckable(input: Element): boolean {
  return input instanceof HTMLInputElement && (input.type === 'checkbox' || input.type === 'radio')
}
if (isCheckable(el)) throw new Error('use toBeChecked()/toHaveFormValues() for checkable inputs')

Type guard

function isCheckableInput(el: Element): el is HTMLInputElement {
  return el instanceof HTMLInputElement && (el.type === 'checkbox' || el.type === 'radio')
}

Prevention

When it happens

Trigger: `expect(page.getByRole('checkbox')).toHaveValue(true)`, `expect(checkboxInput).toHaveValue('on')`, or `expect(radioInput).toHaveValue('yes')`. Any `toHaveValue` call against an `<input type="checkbox">` or `<input type="radio">`.

Common situations: Treating a checkbox like a text field. Migrating assertions from a custom helper that used `.value` directly. Confusing the `value` attribute (always present on inputs) with the checked state.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/2dad6ff80374166e.json. Report an issue: GitHub.