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

  1. Verify the value under test is an array, object, or valid class name before matching
  2. Fix the code that produced null/scalars (e.g. return [] instead of null)
  3. Use anyOf(nullValue(), hasProperty(...)) if null is a legitimate case
  4. 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

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


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)