{"record":{"id":"85dd7f6b96c8c8e5","repo":"BookStackApp/BookStack","slug":"could-not-start-tls-connection-further-details-in","errorCode":null,"errorMessage":"Could not start TLS connection. Further details in the application log.","messagePattern":"Could not start TLS connection\\. Further details in the application log\\.","errorType":"exception","errorClass":"LdapException","httpStatus":null,"severity":"error","filePath":"app/Access/LdapService.php","lineNumber":262,"sourceCode":"\n        if ($ldapConnection === false) {\n            throw new LdapException(trans('errors.ldap_cannot_connect'));\n        }\n\n        // Set any required options\n        if ($this->config['version']) {\n            $this->ldap->setVersion($ldapConnection, $this->config['version']);\n        }\n\n        // Start and verify TLS if it's enabled\n        if ($this->config['start_tls']) {\n            try {\n                $started = $this->ldap->startTls($ldapConnection);\n            } catch (\\Exception $exception) {\n                $error = $exception->getMessage() . ' :: ' . ldap_error($ldapConnection);\n                ldap_get_option($ldapConnection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detail);\n                Log::info(\"LDAP STARTTLS failure: {$error} {$detail}\");\n                throw new LdapException('Could not start TLS connection. Further details in the application log.');\n            }\n            if (!$started) {\n                throw new LdapException('Could not start TLS connection');\n            }\n        }\n\n        $this->ldapConnection = $ldapConnection;\n\n        return $this->ldapConnection;\n    }\n\n    /**\n     * Configure TLS CA certs globally for ldap use.\n     * This will detect if the given path is a directory or file, and set the relevant\n     * LDAP TLS options appropriately otherwise throw an exception if no file/folder found.\n     *\n     * Note: When using a folder, certificates are expected to be correctly named by hash\n     * which can be done via the c_rehash utility.","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/LdapService.php#L244-L280","documentation":"LdapService::getConnection calls startTls() on an LDAP connection to upgrade a plaintext ldap:// connection to TLS. When the PHP LDAP wrapper's startTls() throws (or the underlying ldap_start_tls() fails), the service logs the LDAP error string and the diagnostic message, then throws this generic LdapException because the specific cause (certificate failure, protocol mismatch, etc.) is only in the application log.","triggerScenarios":"Calling getUserWithAttributes, validateUserCredentials, or getParentsOfGroup triggers getConnection, which invokes startTls() against an ldap:// server that fails the TLS handshake: untrusted/self-signed CA cert, wrong CA bundle path, hostname mismatch, server not supporting STARTTLS, or TLS protocol version mismatch.","commonSituations":"LDAP server configured without TLS support while 'start_tls' is enabled in BookStack config; corporate proxy stripping STARTTLS; expired or self-signed certificates; missing/incorrect LDAP_TLS_CA_CERT path; OpenLDAP client compiled against a TLS library that rejects the server's ciphers.","solutions":["Check the application log for the 'LDAP STARTTLS failure:' entry which contains the raw ldap_error and diagnostic message","Verify the LDAP server supports STARTTLS (ldapsearch -ZZ -H ldap://host) and that it is enabled server-side","Set the correct CA cert file/directory via the LDAP TLS CA cert config option, or set LDAPTLS_REQCERT=never only for testing","Ensure the certificate hostname matches the LDAP host you connect to and the cert is not expired","If TLS is unnecessary in your environment, disable the start_tls option so connections use ldaps:// or plaintext"],"exampleFix":"// before (php.ini / env)\n; LDAPTLS_CACERT not set, self-signed cert rejected\n// after\nLDAPTLS_CACERT=/etc/ssl/certs/ldap-ca.pem\n// or in BookStack .env\nLDAP_START_TLS=true\nLDAP_TLS_CA_CERT=/etc/ssl/certs/ldap-ca.pem","handlingStrategy":"try-catch","validationCode":"// before connecting, verify the LDAP endpoint supports STARTTLS\n$ok = ($fp = @fsockopen($host, 389, $errno, $errstr, 5)) && stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT) !== false;\nif ($fp) fclose($fp);\nif (!$ok) { /* abort: STARTTLS unavailable */ }","typeGuard":null,"tryCatchPattern":"try {\n    $conn = $ldapService->getUserWithAttributes($userName, $attrs);\n} catch (LdapException $e) {\n    Log::error('LDAP STARTTLS failed', ['msg' => $e->getMessage(),\n        'app_log' => 'see LDAP STARTTLS failure entry for diagnostics']);\n    // fall back to ldaps:// or show a config error page\n}","preventionTips":["Verify with ldapsearch -ZZ that the server supports STARTTLS before wiring it up","Provision a valid CA cert and matching hostname certificate for the LDAP server","Keep LDAP_TLS_CA_CERT configured and mounted in containers","Pin TLS protocol versions compatible between PHP/OpenLDAP and the server"],"tags":["ldap","tls","starttls","network"],"backgroundTag":"ldap-starttls-failed","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}