BookStackApp/BookStack · error · LdapException

Provided path [{$caCertPath}] for LDAP TLS CA certs could no

Error message

Provided path [{$caCertPath}] for LDAP TLS CA certs could not be resolved to an existing location

What it means

configureTlsCaCerts() validates the configured CA cert path with realpath(). If the path does not exist (or symlinks are broken), realpath() returns false and an LdapException is thrown before any LDAP connection is attempted. This is a configuration error surfaced early to fail fast.

Source

Thrown at app/Access/LdapService.php:289

        return $this->ldapConnection;
    }

    /**
     * Configure TLS CA certs globally for ldap use.
     * This will detect if the given path is a directory or file, and set the relevant
     * LDAP TLS options appropriately otherwise throw an exception if no file/folder found.
     *
     * Note: When using a folder, certificates are expected to be correctly named by hash
     * which can be done via the c_rehash utility.
     *
     * @throws LdapException
     */
    protected function configureTlsCaCerts(string $caCertPath): void
    {
        $errMessage = "Provided path [{$caCertPath}] for LDAP TLS CA certs could not be resolved to an existing location";
        $path = realpath($caCertPath);
        if ($path === false) {
            throw new LdapException($errMessage);
        }

        if (is_dir($path)) {
            $this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTDIR, $path);
        } else if (is_file($path)) {
            $this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTFILE, $path);
        } else {
            throw new LdapException($errMessage);
        }
    }

    /**
     * Parse an LDAP server string and return the host suitable for a connection.
     * Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'.
     */
    protected function parseServerString(string $serverString): string
    {
        if (str_starts_with($serverString, 'ldaps://') || str_starts_with($serverString, 'ldap://')) {

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Verify the path exists: run realpath /path/to/certs on the server/container running the app
  2. Fix the LDAP_TLS_CA_CERT value in .env to an existing absolute path
  3. Mount or copy the CA bundle into the container if running in Docker/Kubernetes
  4. Ensure the web-server/PHP process user has permission to traverse the directory path
  5. Clear any config cache (php artisan config:clear) so the corrected value is picked up

Example fix

// before (.env)
LDAP_TLS_CA_CERT=/etc/ssl/certs/ldap-ca.cr
// after
LDAP_TLS_CA_CERT=/etc/ssl/certs/ldap-ca.crt
Defensive patterns

Strategy: validation

Validate before calling

$caPath = config('services.ldap.tls_ca_cert');
if ($caPath && (realpath($caPath) === false)) {
    throw new RuntimeException("LDAP TLS CA path does not exist: {$caPath}");
}

Type guard

function isReadableCertPath(?string $path): bool {
    return $path !== null && realpath($path) !== false && (is_dir($path) || is_file($path));
}

Prevention

When it happens

Trigger: The LDAP TLS CA cert configuration value (LDAP_TLS_CA_CERT) points to a non-existent path; happens on every getConnection() call (via getUserWithAttributes, validateUserCredentials, getParentsOfGroup) while that config value is set.

Common situations: Typo in the .env path; container image without the CA file mounted; path valid on host but not inside Docker; typo'd or moved directory after upgrade; relative path resolved against unexpected working directory.

Understand the failure class

Related errors


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/102626390e431083. Report an issue: GitHub.