hamcrest/hamcrest-php · error · InvalidArgumentException
Must pass an object, array, or class name
Error message
Must pass an object, array, or class name
What it means
Hamcrest's Set/HasProperty-style matcher throws this when the value being introspected for a property is neither an array, an object, nor a string (class name). The library can only test property existence on those three types, so anything else (null, int, bool, float, resource) is rejected with InvalidArgumentException during matches().
Solutions
- Verify the value under test is an array, object, or valid class name before matching
- Fix the code that produced null/scalars (e.g. return [] instead of null)
- Use anyOf(nullValue(), hasProperty(...)) if null is a legitimate case
- Coerce the item: wrap scalars in an array or value object before asserting
Example fix
// before
assertThat($row, hasProperty('name')); // $row can be null
// after
assertThat(is_array($row) ? $row : [], hasProperty('name')); Defensive patterns
Strategy: type-guard
Validate before calling
if (!is_array($item) && !is_object($item) && !(is_string($item) && class_exists($item))) {
throw new PreconditionException('item must be array, object, or class name');
} Type guard
function isHamcrestPropertyTarget($v): bool {
return is_array($v) || is_object($v) || (is_string($v) && class_exists($v));
} Try / catch
try {
assertThat($item, hasProperty('foo'));
} catch (\InvalidArgumentException $e) {
// item was null/scalar: fail with a clearer message
fail('Expected array/object, got: '.gettype($item));
} Prevention
- Never let producers return null for collections; return []
- Add @param array|object|string docblocks and static analysis (PHPStan/Psalm)
- Use declared property types so IDEs catch scalar misuse
- Null-check data before wrapping it in matchers
When it happens
Trigger: Calling hasProperty()/Set::matches() with an $item that is null or a scalar (e.g. assertThat(42, hasProperty('foo')), or a collection containing null entries passed through eachItem).
Common situations: A data-fetching function returned null instead of an array/object; array keys missing so defaults fall through to null; DB rows containing raw scalars; mixed-type arrays from JSON decode.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Each argument or element must be a Hamcrest matcher
- assertThat() requires one to three arguments
- Must pass a valid XML document
- Must pass a valid HTML or XHTML document
AI-assisted analysis of hamcrest/hamcrest-php@aa726aeff9 (2026-09-15).
Data as JSON: /api/errors/de02d2cffd44f10f.
Report an issue: GitHub.
Appendix: source
Thrown at hamcrest/Hamcrest/Core/Set.php:53
{
$this->_property = $property;
$this->_not = $not;
}
public function matches($item): bool
{
if ($item === null) {
return false;
}
$property = $this->_property;
if (is_array($item)) {
$result = isset($item[$property]);
} elseif (is_object($item)) {
$result = isset($item->$property);
} elseif (is_string($item)) {
$result = isset($item::$$property);
} else {
throw new \InvalidArgumentException('Must pass an object, array, or class name');
}
return $this->_not ? !$result : $result;
}
public function describeTo(Description $description): void
{
$description->appendText($this->_not ? 'unset property ' : 'set property ')->appendText($this->_property);
}
public function describeMismatch($item, Description $description): void
{
$value = '';
if (!$this->_not) {
$description->appendText('was not set');
} else {
$property = $this->_property;
if (is_array($item)) {View on GitHub (pinned to aa726aeff9)