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` when the received element is an `<input>` whose `type` is `checkbox` or `radio`. Those input types do not have a single scalar `.value` semantics the way text inputs do — their meaningful state is `checked`, and radio/checkbox groups aggregate across multiple same-named elements. The matcher deliberately refuses to run and points you at the correct matchers.

Solutions

  1. For checkboxes, use `expect(el).toBeChecked()` (or `.not.toBeChecked()`).
  2. For radio groups or multiple checkboxes sharing a `name`, use `expect(form).toHaveFormValues({ groupName: 'value' })`.
  3. If you genuinely need the raw `value` attribute, read `el.value` directly and assert with `toBe`.

Example fix

// before
expect(checkboxEl).toHaveValue('on')

// after
expect(checkboxEl).toBeChecked()
// or, for a radio group:
expect(form).toHaveFormValues({ role: 'admin' })
Defensive patterns

Strategy: validation

Validate before calling

const tag = element.tagName
const type = (element as HTMLInputElement).type
if (tag === 'INPUT' && (type === 'checkbox' || type === 'radio')) {
  // use the correct matcher instead
  expect(element).toBeChecked()
} else {
  expect(element).toHaveValue(value)
}

Type guard

function isCheckableInput(el: Element): el is HTMLInputElement {
  return el.tagName === 'INPUT'
    && ['checkbox', 'radio'].includes((el as HTMLInputElement).type)
}

Prevention

When it happens

Trigger: Calling `expect(checkboxEl).toHaveValue('on')` or `expect(radioEl).toHaveValue('yes')` where the element is `type="checkbox"` or `type="radio"`. The guard at toHaveValue.ts:27-30 checks `isInputElement(htmlElement) && ['checkbox','radio'].includes(htmlElement.type)`.

Common situations: Treating a checkbox like a text field; generated/label-based locators that resolve to a hidden checkbox input; porting tests from another library whose `toHaveValue` accepted booleans for checkboxes.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/2dad6ff80374166e. Report an issue: GitHub.

Appendix: 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 1fa9837ec2)