composer/composer · error · TransportException

The configured capath was not valid or could not be read.

Error message

The configured capath was not valid or could not be read.

What it means

Thrown by StreamContextFactory::getTlsDefaults() when a configured ssl.capath either is not a directory or is not readable. capath must be an OpenSSL-style hashed certificate directory.

Source

Thrown at src/Composer/Util/StreamContextFactory.php:233

         * Attempt to find a local cafile or throw an exception if none pre-set
         * The user may go download one if this occurs.
         */
        if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
            $result = CaBundle::getSystemCaRootBundlePath($logger);

            if (is_dir($result)) {
                $defaults['ssl']['capath'] = $result;
            } else {
                $defaults['ssl']['cafile'] = $result;
            }
        }

        if (isset($defaults['ssl']['cafile']) && (!Filesystem::isReadable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $logger))) {
            throw new TransportException('The configured cafile was not valid or could not be read.');
        }

        if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !Filesystem::isReadable($defaults['ssl']['capath']))) {
            throw new TransportException('The configured capath was not valid or could not be read.');
        }

        /**
         * Disable TLS compression to prevent CRIME attacks where supported.
         */
        $defaults['ssl']['disable_compression'] = true;

        return $defaults;
    }

    /**
     * A bug in PHP prevents the headers from correctly being sent when a content-type header is present and
     * NOT at the end of the array
     *
     * This method fixes the array by moving the content-type header to the end
     *
     * @link https://bugs.php.net/bug.php?id=61548
     * @param  string|string[] $header

View on GitHub (pinned to 6ffc117740)

Solutions

  1. Point ssl.capath at an actual OpenSSL hashed certificate directory (c_rehash), or unset it and use ssl.cafile instead.
  2. Fix read permissions on the directory.
  3. If unsure, unset the manual capath and let Composer use the system bundle.

Example fix

// before
composer config ssl.capath /etc/ssl/single-cert.pem
// after: use a real hashed dir, or fall back to cafile
composer config --unset ssl.capath
Defensive patterns

Strategy: validation

Validate before calling

$capath = $configuredCapath;
if ($capath && (!is_dir($capath) || !is_readable($capath))) {
    throw new \RuntimeException('Invalid capath: '.$capath);
}

Prevention

When it happens

Trigger: ssl.capath is set in config/options and either is_dir() is false or Filesystem::isReadable() is false at StreamContextFactory.php:232.

Common situations: Pointing capath at a single .pem file instead of a hashed cert directory; wrong path; missing read permissions; the directory has no hashed symlinks so OpenSSL can't use it (though Composer only checks dir + readable here).

Related errors


AI-assisted analysis of composer/composer@6ffc117740 (2026-08-07). Data as JSON: /api/errors/8b5d63590ce6c87a. Report an issue: GitHub.