{"record":{"id":"f9bbfd4c08da1f98","repo":"psf/requests","slug":"could-not-find-the-tls-certificate-file-invalid-p","errorCode":null,"errorMessage":"Could not find the TLS certificate file, invalid path: {conn.cert_file}","messagePattern":"Could not find the TLS certificate file, invalid path: (.+?)","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"src/requests/adapters.py","lineNumber":356,"sourceCode":"\n            if not os.path.isdir(cert_loc):\n                conn.ca_certs = cert_loc\n            else:\n                conn.ca_cert_dir = cert_loc\n        else:\n            conn.cert_reqs = \"CERT_NONE\"\n            conn.ca_certs = None\n            conn.ca_cert_dir = None\n\n        if cert:\n            if not isinstance(cert, basestring):\n                conn.cert_file = cert[0]\n                conn.key_file = cert[1]\n            else:\n                conn.cert_file = cert\n                conn.key_file = None\n            if conn.cert_file and not os.path.exists(conn.cert_file):\n                raise OSError(\n                    f\"Could not find the TLS certificate file, \"\n                    f\"invalid path: {conn.cert_file}\"\n                )\n            if conn.key_file and not os.path.exists(conn.key_file):\n                raise OSError(\n                    f\"Could not find the TLS key file, invalid path: {conn.key_file}\"\n                )\n\n    def build_response(self, req: PreparedRequest, resp: Any) -> Response:\n        \"\"\"Builds a :class:`Response <requests.Response>` object from a urllib3\n        response. This should not be called from user code, and is only exposed\n        for use when subclassing the\n        :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`\n\n        :param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response.\n        :param resp: The urllib3 response object.\n        :rtype: requests.Response\n        \"\"\"","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/psf/requests/blob/8068356288978c4f54661ae6f95afe0e0831885e/src/requests/adapters.py#L338-L374","documentation":"Raised during cert_verify when a client certificate is supplied (cert=...) but the resolved certificate file path does not exist on disk. The cert argument may be a single path string or a (cert, key) tuple; conn.cert_file is set from it and then os.path.exists is checked. A missing file aborts before the TLS handshake so the failure is surfaced as a config error rather than an opaque SSL error.","triggerScenarios":"Triggered by passing cert=\"/path/client.pem\" (or cert=(\"/path/client.crt\", \"/path/client.key\")) where the first element does not exist, in calls to request/get/post or when configuring an HTTPAdapter/Session with a cert. Fires for both the single-string and tuple forms once conn.cert_file is non-empty.","commonSituations":"Common with mTLS clients where the cert path is environment-specific and the value was hardcoded, when a deployment mounts secrets at a different path than the code expects, when relative paths are resolved against an unexpected working directory, or after secret rotation replaced the file with a new name.","solutions":["Check the path exists with os.path.exists before passing it as cert; resolve it to an absolute path first.","Confirm the file is readable by the process user (permissions, mount, volume).","For containerized apps: verify the secret/configmap is mounted at the exact path and the mount is not read-only-missing.","If using a tuple, ensure the cert file is the first element and the key the second.","In CI, fail fast by asserting the cert path during startup health checks rather than at first request."],"exampleFix":"# before\nsession.cert = \"/etc/secrets/client.crt\"  # file absent -> OSError\n\n# after\nimport os\ncert_path = os.path.abspath(\"/etc/secrets/client.crt\")\nassert os.path.exists(cert_path), f\"client cert missing: {cert_path}\"\nsession.cert = cert_path","handlingStrategy":"validation","validationCode":"import os\n\ndef resolve_client_cert(cert):\n    \"\"\"Validate cert arg; return it unchanged if the file(s) exist.\"\"\"\n    if cert is None:\n        return None\n    if isinstance(cert, str):\n        if not os.path.exists(cert):\n            raise FileNotFoundError(f\"client cert not found: {cert}\")\n    elif isinstance(cert, (tuple, list)):\n        for p in cert:\n            if not os.path.exists(p):\n                raise FileNotFoundError(f\"cert file not found: {p}\")\n    else:\n        raise TypeError(f\"unsupported cert type: {type(cert)}\")\n    return cert\n\nsession.cert = resolve_client_cert(config[\"client_cert\"])","typeGuard":"import os\n\ndef is_valid_client_cert(cert) -> bool:\n    if cert is None:\n        return True\n    if isinstance(cert, str):\n        return os.path.exists(cert) and os.access(cert, os.R_OK)\n    if isinstance(cert, (tuple, list)) and len(cert) == 2:\n        return all(os.path.exists(p) and os.access(p, os.R_OK) for p in cert)\n    return False","tryCatchPattern":"try:\n    resp = session.get(url)\nexcept OSError as e:\n    if \"TLS certificate file\" in str(e):\n        # re-check the path, log, and surface a clear config error\n        raise RuntimeError(f\"client cert path invalid: {session.cert}\") from e\n    raise","preventionTips":["Mount mTLS secrets at stable, documented paths; assert existence at startup.","Use absolute paths for cert files to avoid working-directory surprises.","Keep cert and key in the same secret volume to avoid partial deploys.","Rotate certs with a deploy that updates both path and contents together."],"tags":["tls","client-cert","mutual-tls","config","filesystem"],"backgroundTag":null,"analyzedSha":"8068356288978c4f54661ae6f95afe0e0831885e","analyzedAt":"2026-08-11T20:11:09.238Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}