{"record":{"id":"dd2a87ad815fe70d","repo":"guzzle/promises","slug":"you-cannot-create-a-rejectedpromise-with-a-promise","errorCode":null,"errorMessage":"You cannot create a RejectedPromise with a promise.","messagePattern":"You cannot create a RejectedPromise with a promise\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/RejectedPromise.php","lineNumber":31,"sourceCode":" * @template TValue = never\n * @template TReason = mixed\n *\n * @implements PromiseInterface<TValue, TReason>\n *\n * @final\n */\nclass RejectedPromise implements PromiseInterface\n{\n    /** @var TReason */\n    private $reason;\n\n    /**\n     * @param TReason $reason\n     */\n    public function __construct($reason)\n    {\n        if (is_object($reason) && method_exists($reason, 'then')) {\n            throw new \\InvalidArgumentException(\n                'You cannot create a RejectedPromise with a promise.'\n            );\n        }\n\n        $this->reason = $reason;\n    }\n\n    /**\n     * @template TFulfilledValue = never\n     * @template TFulfilledReason = never\n     * @template TRejectedValue = never\n     * @template TRejectedReason = never\n     *\n     * @param (callable(TValue): (TFulfilledValue|PromiseInterface<TFulfilledValue, TFulfilledReason>))|null $onFulfilled Invoked when the promise fulfills.\n     * @param (callable(TReason): (TRejectedValue|PromiseInterface<TRejectedValue, TRejectedReason>))|null   $onRejected  Invoked when the promise is rejected.\n     *\n     * @return ($onRejected is null ? self<TValue, TReason> : PromiseInterface<TRejectedValue, TRejectedReason|\\Throwable>)\n     */","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/guzzle/promises/blob/42118e66a53c492effaf92bc357e931985d5c6f9/src/RejectedPromise.php#L13-L49","documentation":"A RejectedPromise represents an already-known rejection reason, so its constructor rejects any object exposing a then() method (a promise or thenable). Nesting a promise as a rejection reason would produce a rejected-promise-of-a-promise, which the library's unwrapping rules cannot represent; the reason must be a concrete value such as an exception.","triggerScenarios":"new RejectedPromise($r) where $r is any object with a then() method: another Promise, FulfilledPromise, RejectedPromise, or a foreign thenable.","commonSituations":"Rejecting with the result of a failed request before unwrapping it; converting errors from another promise library; helper functions that pass reasons through unmodified when the reason is itself a promise; test fixtures double-wrapping reasons.","solutions":["Unwrap first: pass $reason->wait() or extract the exception/value the inner promise settles with.","Use \\GuzzleHttp\\Promise\\reject($promise) style helpers or \\GuzzleHttp\\Promise\\rejection_for($reason) only with non-thenable reasons.","If the intent is to forward a failure, return/chain the failing promise directly rather than wrapping it.","Type-check reasons in your own API and convert promises before constructing."],"exampleFix":"// before\nreturn new RejectedPromise($failedPromise); // InvalidArgumentException\n// after\nreturn $failedPromise; // just chain the failing promise","handlingStrategy":"type-guard","validationCode":"if (is_object($reason) && method_exists($reason, 'then')) {\n    throw new \\InvalidArgumentException('Reason must not be a promise/thenable');\n}","typeGuard":"function assertNotThenable($reason): void\n{\n    if (is_object($reason) && method_exists($reason, 'then')) {\n        throw new \\InvalidArgumentException('Cannot wrap a promise as a reason; unwrap it first.');\n    }\n}","tryCatchPattern":"try {\n    $p = new \\GuzzleHttp\\Promise\\RejectedPromise($reason);\n} catch (\\InvalidArgumentException $e) {\n    return $reason; // just chain the failing promise directly\n}","preventionTips":["Reasons must be concrete values (typically \\Throwable); unwrap promises before using them as reasons.","When converting failures between promise libraries, chain the failing promise rather than re-wrapping it.","Type-check unknown reasons with method_exists($r, 'then') before constructing."],"tags":["promises","constructor","type-mismatch","guzzle"],"backgroundTag":"invalid-constructor-argument","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"}