%d expands to empty string
The problem is that your username lost the domain. Dovecot doesn't keep track of the domain separately from username, so if something changes username from "user@domain" to just plain "user", the domain is lost and %d returns nothing. If you have auth_debug=yes, this shows up in logs like:
Info: auth(email@example.com): username changed firstname.lastname@example.org -> user
Below are some of the most common reasons for this.
auth_username_format = %Ln lowercases the username but also drops the domain. Use auth_username_format = %Lu instead.
auth_username_format changes the username permanently, currently it's not possible to make it affect only the authentication part.
password_query gets often misconfigured to drop the domain if username and domain are stored separately. For example:
# BROKEN: password_query = SELECT username AS user, password FROM users WHERE username = '%n' AND domain = '%d'
The "username AS user" changes the username permanently and the domain is dropped. You can instead use:
# MySQL: password_query = SELECT concat(username, '@', domain) AS user, password FROM users WHERE username = '%n' AND domain = '%d'
With v1.1+ you can return username and domain fields separately and Dovecot will merge them into a single user field:
# v1.1+ only: password_query = SELECT username, domain, password FROM users WHERE username = '%n' AND domain = '%d'