{"id":"bc7f6f35fce9bb8d","repo":"guzzle/guzzle","slug":"cannot-use-different-passphrases-for-cert-and-ssl","errorCode":null,"errorMessage":"Cannot use different passphrases for cert and ssl_key with the stream handler; %s conflicts with an existing TLS passphrase.","messagePattern":"Cannot use different passphrases for cert and ssl_key with the stream handler; (.+?) conflicts with an existing TLS passphrase\\.","errorType":"validation","errorClass":"GuzzleHttp\\Exception\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Handler/StreamHandler.php","lineNumber":1422,"sourceCode":"            throw new InvalidArgumentException(\\sprintf('Invalid %s request option', $option));\n        }\n\n        return [$value, $passphrase];\n    }\n\n    private static function setTlsPassphrase(\n        #[\\SensitiveParameter]\n        array &$options,\n        #[\\SensitiveParameter]\n        ?string $passphrase,\n        string $option\n    ): void {\n        if ($passphrase === null) {\n            return;\n        }\n\n        if (isset($options['ssl']['passphrase']) && $options['ssl']['passphrase'] !== $passphrase) {\n            throw new InvalidArgumentException(\\sprintf('Cannot use different passphrases for cert and ssl_key with the stream handler; %s conflicts with an existing TLS passphrase.', $option));\n        }\n\n        $options['ssl']['passphrase'] = $passphrase;\n    }\n\n    /**\n     * @param mixed $value as passed via Request transfer options.\n     */\n    private static function assertStreamTlsType(string $option, $value): void\n    {\n        if (!\\is_string($value) || $value === '') {\n            throw new InvalidArgumentException(\\sprintf('%s must be a non-empty string', $option));\n        }\n\n        if (Psr7\\Utils::asciiToUpper($value) !== 'PEM') {\n            throw new InvalidArgumentException(\\sprintf('The stream handler only supports \"PEM\" for the %s request option.', $option));\n        }\n    }","sourceCodeStart":1404,"sourceCodeEnd":1440,"githubUrl":"https://github.com/guzzle/guzzle/blob/9b200fc5805036b331d6031199880dadecae0275/src/Handler/StreamHandler.php#L1404-L1440","documentation":"Thrown by StreamHandler::setTlsPassphrase() when the cert and ssl_key options each carry a passphrase and the two passphrases differ. PHP's stream SSL context exposes a single passphrase field, so the stream handler cannot honor two different values; it fails closed rather than silently picking one.","triggerScenarios":"Setting both ['cert' => ['/path/cert.pem', 'passA']] and ['ssl_key' => ['/path/key.pem', 'passB']] with passA !== passB in the same request options, under the StreamHandler.","commonSituations":"Migrating from cURL (which accepts CURLOPT_SSLCERTPASSWD and CURLOPT_SSLKEYPASSWD independently) to the stream handler, or copying two halves of a split-credential config whose passphrase fields drifted out of sync.","solutions":["Use the same passphrase string for both cert and ssl_key.","Set the passphrase on only one of the two options (cert or ssl_key) and omit it from the other.","If the cert and key genuinely need different passphrases, switch to a cURL-based handler (CurlHandler/CurlMultiHandler)."],"exampleFix":"// before\n['cert' => ['/c.pem', 'passA'], 'ssl_key' => ['/k.pem', 'passB']]\n\n// after\n['cert' => ['/c.pem', 'shared'], 'ssl_key' => ['/k.pem', 'shared']]","handlingStrategy":"validation","validationCode":"// Ensure cert and ssl_key share a passphrase\n$certPass = is_array($options['cert'] ?? null) ? ($options['cert'][1] ?? null) : null;\n$keyPass  = is_array($options['ssl_key'] ?? null) ? ($options['ssl_key'][1] ?? null) : null;\nif ($certPass !== null && $keyPass !== null && $certPass !== $keyPass) {\n    throw new InvalidArgumentException('cert and ssl_key passphrases differ');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set the passphrase on only one of cert/ssl_key; PHP's stream context uses a single passphrase field.","If you need two distinct passphrases, use CurlHandler instead of StreamHandler."],"tags":["stream-handler","tls","client-cert","passphrase","validation"],"analyzedSha":"9b200fc5805036b331d6031199880dadecae0275","analyzedAt":"2026-08-04T21:24:26.648Z","schemaVersion":2}