{"record":{"id":"74e7b233c8221b49","repo":"pestphp/pest","slug":"method-s-does-not-exist-in-s","errorCode":null,"errorMessage":"Method [%s] does not exist in [%s].","messagePattern":"Method \\[(.+?)\\] does not exist in \\[(.+?)\\]\\.","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"src/Expectation.php","lineNumber":320,"sourceCode":"\n        return $this;\n    }\n\n    /**\n     * @param  array<int, mixed>  $parameters\n     * @return Expectation<TValue>|HigherOrderExpectation<Expectation<TValue>, TValue>\n     */\n    public function __call(string $method, array $parameters): Expectation|HigherOrderExpectation|PendingArchExpectation|ArchExpectation\n    {\n        if (! self::hasMethod($method)) {\n            if (! is_object($this->value) && method_exists(PendingArchExpectation::class, $method)) {\n                $pendingArchExpectation = new PendingArchExpectation($this, []);\n\n                return $pendingArchExpectation->$method(...$parameters); // @phpstan-ignore-line\n            }\n\n            if (! is_object($this->value)) {\n                throw new BadMethodCallException(sprintf(\n                    'Method [%s] does not exist in [%s].',\n                    $method,\n                    gettype($this->value)\n                ));\n            }\n\n            /* @phpstan-ignore-next-line */\n            return new HigherOrderExpectation($this, call_user_func_array($this->value->$method(...), $parameters));\n        }\n\n        $closure = $this->getExpectationClosure($method);\n        $reflectionClosure = new \\ReflectionFunction($closure);\n        $expectation = $reflectionClosure->getClosureThis();\n\n        if ($reflectionClosure->getReturnType()?->__toString() === ArchExpectation::class) {\n            return $closure(...$parameters);\n        }\n","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/pestphp/pest/blob/1af74a215c3a89bc7a44fc6f9322e369eaad2423/src/Expectation.php#L302-L338","documentation":"When you call an unknown method on an Expectation, Pest's __call tries three routes: a registered expectation, forwarding to PendingArchExpectation for arch-style methods (only when the value is not an object), or proxying to a real method on the underlying object (higher-order). If the method is none of those and the value is not an object, you get BadMethodCallException naming the method and the value's type. Typically this means a misspelled expectation name applied to a scalar/array/null value.","triggerScenarios":"expect('foo')->toUpercase() (misspelled toBeUppercase); expect(5)->toHaveItems(3) (method exists only on the object proxy path); calling a custom expectation before it was registered with expect()->extend(); calling an object-proxied method (e.g., ->getName()) on a scalar or array.","commonSituations":"Typos in expectation names (toBeTuure, toEqualRecursive); upgrading Pest and using an expectation introduced in a newer version; custom expectations defined in a Helpers/Expectations.php file that is not loaded; assuming an object-style proxy works on arrays.","solutions":["Check the exact spelling against Pest's expectation API for your installed version (composer show pestphp/pest).","If it is a custom expectation, make sure expect()->extend(...) runs before use — e.g., the file is listed in the tests directory structure Pest auto-loads (Expectations.php).","For object proxies, ensure the underlying value really is an object with that method; for arrays/scalars, use the array/scalar expectation instead.","If you need the method to exist, register it: expect()->extend('toFoo', fn () => ...)."],"exampleFix":"// before\nexpect('pest')->toUppercase(); // BadMethodCallException\n// after\nexpect('PEST')->toBeUppercase();","handlingStrategy":"type-guard","validationCode":"use Pest\\Expectation;\n\nif (! Expectation::hasMethod('toFoo')) {\n    expect()->extend('toFoo', fn (mixed $arg = null) => /* ... */);\n}\nexpect($value)->toFoo();","typeGuard":"// object-proxy path: verify the underlying object has the method\nif (is_object($value) && method_exists($value, 'getName')) {\n    expect($value)->getName()->toBe('Pest');\n} else {\n    expect($value)->toBeObject(); // fail with a clear message\n}","tryCatchPattern":null,"preventionTips":["Run Pint/an editor with Pest plugin so expectation names autocomplete and typos surface immediately.","Register custom expectations in Expectations.php (or before first use) so they exist before any call.","Pin the Pest version in CI to one whose expectation API matches your suite's usage."],"tags":["pest","expectation","undefined-method","typo","magic-methods"],"backgroundTag":"undefined-method-call","analyzedSha":"1af74a215c3a89bc7a44fc6f9322e369eaad2423","analyzedAt":"2026-08-21T02:16:38.132Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}