{"id":"253669b89c0b6cf1","repo":"guzzle/guzzle","slug":"ssl-ca-bundle-not-found-s","errorCode":null,"errorMessage":"SSL CA bundle not found: %s","messagePattern":"SSL CA bundle not found: (.+?)","errorType":"validation","errorClass":"GuzzleHttp\\Exception\\InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Handler/CurlFactory.php","lineNumber":2468,"sourceCode":"    private function applyHandlerOptions(\n        #[\\SensitiveParameter]\n        EasyHandle $easy,\n        #[\\SensitiveParameter]\n        array &$conf\n    ): void {\n        $options = $easy->options;\n        if (isset($options['verify'])) {\n            if ($options['verify'] === false) {\n                unset($conf[\\CURLOPT_CAINFO]);\n                $conf[\\CURLOPT_SSL_VERIFYHOST] = 0;\n                $conf[\\CURLOPT_SSL_VERIFYPEER] = false;\n            } else {\n                $conf[\\CURLOPT_SSL_VERIFYHOST] = 2;\n                $conf[\\CURLOPT_SSL_VERIFYPEER] = true;\n                if (\\is_string($options['verify'])) {\n                    // Throw an error if the file/folder/link path is not valid or doesn't exist.\n                    if (!\\file_exists($options['verify'])) {\n                        throw new InvalidArgumentException(\\sprintf('SSL CA bundle not found: %s', Psr7\\DiagnosticValue::escape($options['verify'])));\n                    }\n                    // If it's a directory or a link to a directory use CURLOPT_CAPATH.\n                    // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.\n                    if (\n                        \\is_dir($options['verify'])\n                        || (\n                            \\is_link($options['verify']) === true\n                            && ($verifyLink = \\readlink($options['verify'])) !== false\n                            && \\is_dir($verifyLink)\n                        )\n                    ) {\n                        $conf[\\CURLOPT_CAPATH] = $options['verify'];\n                    } else {\n                        $conf[\\CURLOPT_CAINFO] = $options['verify'];\n                    }\n                }\n            }\n        }","sourceCodeStart":2450,"sourceCodeEnd":2486,"githubUrl":"https://github.com/guzzle/guzzle/blob/9b200fc5805036b331d6031199880dadecae0275/src/Handler/CurlFactory.php#L2450-L2486","documentation":"Thrown in applyHandlerOptions() when the 'verify' option is a non-empty string used as a CA bundle path but file_exists() reports it does not exist as a file, directory, or symlink. Guzzle distinguishes file (CURLOPT_CAINFO) vs directory (CURLOPT_CAPATH) CA stores and validates the path exists before handing it to cURL. The %s is the escaped user-supplied path via Psr7\\DiagnosticValue::escape.","triggerScenarios":"Setting ['verify' => '/etc/ssl/cacert.pem'] (or a directory) where the path does not exist on the host; relative paths resolved against an unexpected cwd; deploy missing the bundled CA file.","commonSituations":"Bundling a cacert.pem that was not shipped to the container; environment-specific paths (different on dev vs prod); typo in the path; running in a minimal Alpine image without ca-certificates installed.","solutions":["Point 'verify' at an existing CA bundle file or directory (e.g. download https://curl.se/ca/cacert.pem, or use the system directory like /etc/ssl/certs).","Install ca-certificates on the OS (apt-get install ca-certificates / apk add ca-certificates) and use the system path.","If you intentionally do not want verification, set 'verify' => false explicitly (not recommended for production)."],"exampleFix":"// before\n['verify' => '/app/config/cacert.pem'] // file not shipped in image\n// after (ship the file) or use the system bundle\n['verify' => ini_get('openssl.cafile') ?: '/etc/ssl/certs/ca-certificates.crt']","handlingStrategy":"validation","validationCode":"if (isset($options['verify']) && is_string($options['verify']) && !file_exists($options['verify'])) {\n    throw new InvalidArgumentException('SSL CA bundle not found: ' . $options['verify']);\n}","typeGuard":"function caBundleExists($verify): bool {\n    return !is_string($verify) || file_exists($verify);\n}","tryCatchPattern":null,"preventionTips":["Ship cacert.pem in your artifact/image or install the OS ca-certificates package.","Use absolute paths; verify at startup with is_readable().","Default to the system bundle via openssl.cafile/openssl.capath ini settings."],"tags":["tls","configuration","ssl","ca-bundle","deployment"],"analyzedSha":"9b200fc5805036b331d6031199880dadecae0275","analyzedAt":"2026-08-04T21:24:26.648Z","schemaVersion":2}