{"record":{"id":"fabe89900882e8b9","repo":"pestphp/pest","slug":"unhandled-match-value","errorCode":null,"errorMessage":"Unhandled match value.","messagePattern":"Unhandled match value\\.","errorType":"exception","errorClass":"ExpectationFailedException","httpStatus":null,"severity":"error","filePath":"src/Expectation.php","lineNumber":268,"sourceCode":"            if ($subject != $key) { // @pest-arch-ignore-line\n                continue;\n            }\n\n            $matched = true;\n\n            if (is_callable($callback)) {\n                $callback(new self($this->value));\n\n                continue;\n            }\n\n            $this->and($this->value)->toEqual($callback);\n\n            break;\n        }\n\n        if ($matched === false) {\n            throw new ExpectationFailedException('Unhandled match value.');\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param  (callable(): bool)|bool  $condition\n     * @param  callable(Expectation<TValue>): mixed  $callback\n     * @return self<TValue>\n     */\n    public function unless(callable|bool $condition, callable $callback): Expectation\n    {\n        $condition = is_callable($condition)\n            ? $condition\n            : static fn (): bool => $condition;\n\n        return $this->when(! $condition(), $callback);\n    }","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/pestphp/pest/blob/1af74a215c3a89bc7a44fc6f9322e369eaad2423/src/Expectation.php#L250-L286","documentation":"expect($value)->match($subject, $expressions) walks the expression map and loosely compares each key against the subject; if no key matches, Pest throws ExpectationFailedException('Unhandled match value.') because the expectation cannot proceed. Unlike PHP's match, there is no implicit default arm here — every reachable subject value needs an explicit key.","triggerScenarios":"expect($x)->match($status, ['active' => fn ($v) => $v->toBe(1), 'blocked' => 0]) with $status = 'pending'; a dynamic subject (method return, enum ->value, env flag) that gained a new value not covered by the map; loose-comparison traps such as expecting 0 to match the key '0' differently than intended.","commonSituations":"Switch-like assertions over statuses, locales, or feature flags where a new case is added to the code but not the test map; data-driven tests where the subject comes from a fixture; typos or casing differences between subject and map keys (loose == does not bridge 'Active' vs 'active').","solutions":["Add a map entry whose key equals the subject value reported in the failure.","Normalize the subject before matching: strtolower()/trim() the subject and keys, or match on a canonical enum ->value.","If a catch-all is needed, compute it explicitly: $expressions[$subject] ?? $fallbackAssertion instead of relying on a 'default' key that only matches a literal 'default' subject.","Replace with when()/unless() chains when the set of possible subjects is open-ended."],"exampleFix":"// before\nexpect($plan)->match($user->status, [\n    'active' => fn ($v) => $v->toBe('pro'),\n]);\n// $user->status === 'trial' -> Unhandled match value.\n// after\nexpect($plan)->match($user->status, [\n    'active' => fn ($v) => $v->toBe('pro'),\n    'trial' => fn ($v) => $v->toBe('free'),\n]);","handlingStrategy":"validation","validationCode":"$expressions = ['active' => 1, 'blocked' => 0];\n$subject = strtolower($user->status);\nif (! array_key_exists($subject, $expressions)) {\n    throw new LogicException(\"No match arm for status [{$subject}]\");\n}\nexpect($plan)->match($subject, $expressions);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the subject and the expression keys canonicalized (same case, trimmed) before match().","When the subject set is open-ended, use a computed fallback ($expressions[$subject] ?? $fallback) instead of relying on match().","Add a new arm in the same commit that adds a new status/value to production code."],"tags":["pest","expectation","match","unhandled-case","switch"],"backgroundTag":"unhandled-match-case","analyzedSha":"1af74a215c3a89bc7a44fc6f9322e369eaad2423","analyzedAt":"2026-08-21T02:16:38.132Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}