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
- For checkboxes use `toBeChecked()`/`toBeUnchecked()`.
- For forms containing checkboxes/radios use `toHaveFormValues({ groupName: expectedValueOrArray })`.
- 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
- Use toBeChecked()/toBeUnchecked() for checkboxes and radios.
- Use toHaveFormValues() to assert checkable groups by name.
- Reserve toHaveValue() for text, number, select, and similar single-value inputs.
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
- toHaveFormValues must be called on a form or a fieldset, ins
- Multiple form elements with the same name must be of the sam
- 'toMatchScreenshot' cannot be used with "not"
- received value must ${expectedString} or a Locator that retu
- Element not found: ${v.element}
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/2dad6ff80374166e.json.
Report an issue: GitHub.