Skip to content
Microsoft SQL Server

SQL Server Error 18487

Login failed: the password of the account has expired

Severity 14 Logins & Permissions
Applies to: All supported SQL Server versions (2016 to 2025) and Azure SQL Managed Instance, for SQL logins with CHECK_EXPIRATION = ON
Last technically reviewed 24 October 2026 on SQL Server 2025 (17.0.1145.4)
The full message
Login failed for user 'app_login'.  Reason: The password of the account has expired.
Error number
18487
Severity
14 (user-correctable error)
State
Not documented by Microsoft (not reproduced here)
Product
Microsoft SQL Server Database Engine
Versions
All supported SQL Server versions (2016 to 2025) and Azure SQL Managed Instance, for SQL logins with CHECK_EXPIRATION = ON
Last reviewed
24 October 2026

What it means

Error 18487 means the SQL login uses password expiration (CHECK_EXPIRATION = ON) and its password is older than the Windows maximum password age, so it must be changed before the login can connect.

SQL logins with CHECK_EXPIRATION = ON follow the Maximum password age of the Windows password policy on the server (or the domain policy that applies to it). Once the password is older than that, SQL Server refuses new connections with 18487 at severity 14 and writes the failure to the error log. Microsoft's password policy article describes it the same way: accounts with expired passwords are disabled until the password is changed.

Like error 18488, the reason is only given once the password itself has been accepted, so the message tells you the password was right but too old. It usually appears suddenly on a working system, on the day the password reaches its age limit, which is why it tends to break application logins that nobody has touched for weeks.

Common causes

  • An application or service login was created with CHECK_EXPIRATION = ON (the SQL Server Management Studio box "Enforce password expiration"), and nobody rotated its password.
  • The Windows or domain password policy lowered the maximum password age, so existing passwords expired earlier than planned.
  • A person's SQL login was not used for a long time and the password aged past the limit.

Diagnose it

Read-only These queries only read metadata and dynamic management views. They do not change data, permissions or configuration, so they are safe to run first.

Has the password expired, and when was it set?

SELECT name, is_policy_checked, is_expiration_checked,
       LOGINPROPERTY(name, 'IsExpired')           AS is_expired,
       LOGINPROPERTY(name, 'DaysUntilExpiration') AS days_until_expiration,
       LOGINPROPERTY(name, 'PasswordLastSetTime') AS password_last_set
FROM sys.sql_logins
WHERE name = N'app_login';
What to look for

is_expired = 1 confirms the cause. password_last_set plus the maximum password age tells you when it expired.

Which SQL logins will expire soon?

SELECT name,
       LOGINPROPERTY(name, 'DaysUntilExpiration') AS days_until_expiration
FROM sys.sql_logins
WHERE is_expiration_checked = 1
ORDER BY CAST(LOGINPROPERTY(name, 'DaysUntilExpiration') AS int);
What to look for

Small numbers are the next 18487 failures waiting to happen. Rotate those passwords now.

Read the failures in the error log

Requires membership of securityadmin or sysadmin.

EXEC sp_readerrorlog 0, 1, N'has expired';
What to look for

The login name and client address of each failed attempt.

How to fix it

Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.

Set a new password (administrator)

Changes permissions

Setting a new password resets its age. Update every application that uses the login in the same change.

ALTER LOGIN [app_login] WITH PASSWORD = N'Use-a-strong-unique-password-1';

Let the person change the password at login

Client or network side

A person with an expired password can choose a new one while connecting, for example with sqlcmd -z (we tested this option with a must-change login, error 18488, not with an expired one).

-- sqlcmd -S SQL01 -U app_login -z "New-strong-password-1" -Q "SELECT 1"

Rotate service passwords on a schedule

Changes permissions

For application logins, keep CHECK_POLICY = ON and rotate the password from a secrets manager before DaysUntilExpiration reaches zero, using the second diagnostic as an alert. Whether an application login should use expiration at all is a policy decision for your security team; do not switch it off just to clear one failure.

Examples

A login whose password is older than the maximum password age

Shown as documented in sys.messages and Microsoft's password policy article, not reproduced: it needs a password older than the Windows maximum password age, and the lab policy was not changed. The client and error log layout follows the reproduced error 18488.

-- The login uses expiration, and the password is too old:
SELECT LOGINPROPERTY(N'app_login', 'IsExpired') AS is_expired;  -- 1

-- A connection with the correct password then fails:
-- sqlcmd -S . -C -U app_login -Q "SELECT 1"
Result
Login failed for user 'app_login'.  Reason: The password of the account has expired.

How to prevent it

Monitor DaysUntilExpiration for every SQL login with expiration on, and rotate passwords well before the limit. Prefer Windows or Microsoft Entra authentication for services where you can, so password age is handled by the directory instead of connection strings.

Treat a change to the Windows maximum password age as a change that can break SQL logins, and check the expiry list after it. See also error 18456 for other login failures.

Common questions

Where does SQL Server get the expiry period from?

From the Windows password policy that applies to the server (local or domain), through the NetValidatePasswordPolicy API. SQL Server has no separate setting for it.

Does an expired password affect sessions that are already connected?

The message is raised at login, so it concerns new connections. Applications usually notice when their connection pool opens a new connection.

What is the difference between 18487 and 18488?

18487 means the password became too old under the expiration policy. 18488 means an administrator flagged the login with MUST_CHANGE. Both are fixed by setting a new password.

Learn more on CodeWithSQL

Official documentation

Last technically reviewed 24 October 2026; examples and diagnostics run on SQL Server 2025 (17.0.1145.4). Message text checked against the engine's sys.messages catalogue.

Still stuck on a SQL Server error?

Browse the full SQL Server error library, or get hands-on help from an experienced SQL professional.