I use a directory and added a second domain to my Stalwart.
Weird enough, on my domain tab it doesn’t allow me choose the directory to read from.
However, when authenticating from my e-mail client, it works normally and I can send and receive emails.
But when connecting to the /admin/login endpoint, I get this:
2026-05-30T11:33:54Z ERROR Authentication error (auth.error) listenerId = "https", localPort = 443, remoteIp = 10.11.11.111, remotePort = 52036, details = Authentication error (auth.error) { details = "Account does not have a password. If you are using an external directory, make sure to set the password attribute.", causedBy = "crates/common/src/auth/oauth/token.rs:59" }, causedBy = "crates/http/src/auth/oauth/token.rs:127"
What can be the problem?
Stalwart Version
v0.16.x
Installation Method
Docker
Database Backend
FoundationDB
Blob Storage
S3-compatible
Search Engine
Internal
Directory Backend
LDAP
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
Let me look into this error to give you an accurate answer.
The error is directly caused by the interaction between bind authentication and the WebUI’s OAuth token flow. Here’s what’s happening and how to fix it:
Root cause: Your LDAP directory is configured with bindAuthentication: true (which is the default). In this mode, Stalwart authenticates users by binding as them directly – it never reads a password hash from LDAP. However, there is a key requirement: the attrSecretChanged attribute must be properly mapped so Stalwart can track password changes and generate OAuth tokens for the WebUI login. If that attribute is missing or not returned by your LDAP server, the OAuth token path cannot find a “password” value and throws this error.
Things to check/fix in your LDAP Directory object:
attrSecretChanged – This attribute (default ["pwdChangeTime"]) must be present and returned by your LDAP server for entries. If your LDAP schema uses a different attribute name for password change timestamps, update attrSecretChanged to match. For example:
(Use whatever attribute your LDAP server actually populates for password change tracking.)
Alternatively, if bindAuthentication is false (service-account hash comparison mode), ensure attrSecret points to the correct attribute that stores the password hash (default ["userPassword"]), and that your LDAP server actually returns that attribute to the service account.
Why does IMAP/SMTP work but not the WebUI? Email clients authenticate via SASL mechanisms (PLAIN, LOGIN, etc.) which go through a different code path. The WebUI login uses OAuth token issuance, which is where Stalwart needs the password hash or password-change marker to issue a token – and that’s the step that’s failing.
You can configure these settings in the WebUI under Settings > Authentication > Directories, or via the stalwart-cli.
Relevant docs: LDAP Directory – specifically the “Authentication methods” and “Object attributes” sections.
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.
The “Account does not have a password” error fires when the account is found but the directory returns no usable password for it, which for an LDAP-backed user means the directory being consulted is not the one holding that user. That lines up with your symptom: one tree’s users authenticate, the other tree’s users do not.
A couple of things to check. Choosing a different directory per domain is an Enterprise feature; in the community edition every domain resolves to the single default directory, so if the failing users live in a second LDAP that is not the default, the WebUI auth will not find their password even though IMAP/SMTP may resolve them differently. Also, there was a real bug in per-domain external directory resolution that was fixed in 0.16.7, so if you are on Enterprise and below that, upgrade first and retest.
To narrow it down: what exact 0.16.x version are you on, Enterprise or community, and is each domain meant to use its own LDAP or should one default LDAP cover both trees? Confirm the failing users’ bind returns a userPassword attribute.