{"record":{"id":"f3fc97f2050020c3","repo":"guzzle/promises","slug":"exceptionfor-this-reason","errorCode":null,"errorMessage":"exceptionFor($this->reason)","messagePattern":"exceptionFor\\(\\$this->reason\\)","errorType":"exception","errorClass":"dynamic (Create::exceptionFor)","httpStatus":null,"severity":"error","filePath":"src/RejectedPromise.php","lineNumber":93,"sourceCode":"    }\n\n    /**\n     * @template TRejectedValue = never\n     * @template TRejectedReason = never\n     *\n     * @param callable(TReason): (TRejectedValue|PromiseInterface<TRejectedValue, TRejectedReason>) $onRejected Invoked when the promise is rejected.\n     *\n     * @return PromiseInterface<TRejectedValue, TRejectedReason|\\Throwable>\n     */\n    public function otherwise(callable $onRejected): PromiseInterface\n    {\n        return $this->then(null, $onRejected);\n    }\n\n    public function wait(bool $unwrap = true)\n    {\n        if ($unwrap) {\n            throw Create::exceptionFor($this->reason);\n        }\n\n        return null;\n    }\n\n    public function getState(): string\n    {\n        return self::REJECTED;\n    }\n\n    public function resolve($value = null): void\n    {\n        throw new \\LogicException('Cannot resolve a rejected promise');\n    }\n\n    public function reject($reason): void\n    {\n        if ($reason !== $this->reason) {","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/guzzle/promises/blob/42118e66a53c492effaf92bc357e931985d5c6f9/src/RejectedPromise.php#L75-L111","documentation":"RejectedPromise::wait(true) always throws: the promise is already settled as rejected, so wait() converts its stored rejection reason into an exception via Create::exceptionFor($this->reason) and throws it. Unlike Promise::wait(), no resolution can occur - a RejectedPromise is immutable, so every wait(true) call rethrows the same reason.","triggerScenarios":"Calling ->wait() on any instance created with new RejectedPromise($reason) (or returned by helpers that reject eagerly), with the default $unwrap = true. Throws immediately regardless of prior state, because the rejection reason is fixed at construction.","commonSituations":"Test fixtures that seed a RejectedPromise and call wait() to assert the reason surfaces; code paths that short-circuit to a rejected promise (e.g. invalid input checked synchronously before async work) and are later awaited; mixing eager RejectedPromise values into code that assumes wait() returns a value.","solutions":["Wrap the wait() call in try/catch and inspect the caught exception, which is the original rejection reason.","Handle rejection with ->otherwise() or ->then(null, $onRejected) instead of waiting on the rejected promise.","If you only need settlement, call wait(false), which returns null without throwing.","Restructure code so a RejectedPromise is not awaited directly, e.g. recover with ->otherwise(...) to produce a fulfilled promise first."],"exampleFix":"// before\n$result = $rejectedPromise->wait(); // always throws the reason\n\n// after\ntry {\n    $rejectedPromise->wait();\n} catch (\\Throwable $e) {\n    // $e is the reason stored in the RejectedPromise\n}\n// or, without throwing:\n$rejectedPromise->wait(false);","handlingStrategy":"try-catch","validationCode":"// A RejectedPromise is rejected by construction - check before waiting:\nuse GuzzleHttp\\Promise\\RejectedPromise;\nif (!$promise instanceof RejectedPromise) {\n    $value = $promise->wait();\n}","typeGuard":"// Reject the eager rejected-promise case before unwrapping\nfunction safeWait(\\GuzzleHttp\\Promise\\PromiseInterface $p) {\n    if ($p instanceof \\GuzzleHttp\\Promise\\RejectedPromise) {\n        return null; // wait(true) would throw; do not unwrap\n    }\n    return $p->wait();\n}","tryCatchPattern":"try {\n    $rejectedPromise->wait();\n} catch (\\Throwable $reason) {\n    // $reason is exactly the reason the RejectedPromise was constructed with\n}","preventionTips":["Remember RejectedPromise::wait(true) throws unconditionally - never call it expecting a value.","Use wait(false) for side-effect-free, non-throwing settlement.","Prefer ->otherwise() recovery over awaiting a known-rejected promise.","Convert eager rejections with ->otherwise() so downstream code always sees a thenable that resolves normally.","In tests expecting a reason, catch the exception from wait() and assert on it explicitly."],"tags":["promise","rejection","rejected-promise","wait","guzzle-promises"],"backgroundTag":"unhandled-promise-rejection","analyzedSha":"42118e66a53c492effaf92bc357e931985d5c6f9","analyzedAt":"2026-09-14T00:10:14.865Z","contentChangedAt":"2026-09-14T00:10:14.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}