{"record":{"id":"5ce0b59e1e3de64a","repo":"BookStackApp/BookStack","slug":"could-not-find-or-create-a-user-for-ldap-login","errorCode":null,"errorMessage":"Could not find or create a user for LDAP login.","messagePattern":"Could not find or create a user for LDAP login\\.","errorType":"exception","errorClass":"LoginAttemptException","httpStatus":null,"severity":"error","filePath":"app/Access/Guards/LdapSessionGuard.php","lineNumber":87,"sourceCode":"            $this->lastAttempted = $user = $this->provider->retrieveByCredentials([\n                'external_auth_id' => $userDetails['uid'],\n            ]);\n        }\n\n        if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {\n            return false;\n        }\n\n        if (is_null($user)) {\n            try {\n                $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);\n            } catch (UserRegistrationException $exception) {\n                throw new LoginAttemptException($exception->getMessage());\n            }\n        }\n\n        if (!($user instanceof User)) {\n            throw new LoginAttemptException('Could not find or create a user for LDAP login.');\n        }\n\n        // Sync LDAP groups if required\n        if ($this->ldapService->shouldSyncGroups()) {\n            $this->ldapService->syncGroups($user, $username);\n        }\n\n        // Attach avatar if non-existent\n        if (!$user->avatar()->exists()) {\n            $this->ldapService->saveAndAttachAvatar($user, $userDetails);\n        }\n\n        $this->login($user, $remember);\n\n        return true;\n    }\n\n    /**","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Access/Guards/LdapSessionGuard.php#L69-L105","documentation":"LoginAttemptException thrown in LdapSessionGuard::attempt when, after searching LDAP, $user is still not an instance of User. This is a defensive post-condition: neither an existing local user matching the credentials nor a newly created one could be obtained. The library throws it so the login fails explicitly instead of proceeding with a non-user value.","triggerScenarios":"attempt() completes the LDAP lookup and the user-creation branch, yet $user remains null/non-User — e.g. the LDAP query returned no attributes/user, or a code path returned null without throwing a UserRegistrationException.","commonSituations":"LDAP bind succeeds but the search filter/base DN matches no entry for the entered username; external auth ID stored locally doesn't match the LDAP uid after LDAP directory changes; custom overrides or older data shapes returning null from the lookup.","solutions":["Verify the LDAP base DN and user search filter in config so the username resolves to an actual directory entry","Check that the external_auth_id stored on existing users still matches the LDAP uid attribute","Test with the LDAP debug/dump option to see what attributes are returned for the user","Ensure the credentials entered match a real, active LDAP account"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"$details = $ldap->getUserWithAttributes($username);\nif ($details === null || empty($details['uid'])) {\n    abort(401, 'No matching LDAP user');\n}","typeGuard":null,"tryCatchPattern":"try {\n    auth()->guard('ldap')->attempt($credentials);\n} catch (\\BookStack\\Access\\Exceptions\\LoginAttemptException $e) {\n    return back()->with('error', $e->getMessage());\n}","preventionTips":["Validate base DN and search filters with ldapsearch before configuring the app","Re-sync external_auth_id values after LDAP directory migrations","Enable LDAP debug logging when diagnosing login failures"],"tags":["ldap","login","user-lookup"],"backgroundTag":"ldap-user-lookup-failed","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}