Login failed for user 'sa'. (error 18456) means SQL Server received the login and
refused it. The client is never told why: it always sees state 1. The real reason is a state number
in the server's error log (8 for a wrong password, 5 for a login that does not exist), so read that
line first and fix the one thing it names.
In a SQL Server container, a cause that is easy to miss is a reused data volume. A changed
MSSQL_SA_PASSWORD did not change the password stored on an existing volume in this
test, so connect with the old password and run ALTER LOGIN sa WITH PASSWORD, or start
again on a fresh volume if its data is disposable.
The error
PS> .\FixLab.exe 'Server=127.0.0.1,15433;User ID=sa;Password=Second-Pass-2026x;TrustServerCertificate=true' 'SELECT SUSER_SNAME()'
ex.Number = 18456, ex.Class = 14, ex.State = 1
Microsoft.Data.SqlClient.SqlException: Login failed for user 'sa'.
sqlcmd reports the same refusal as
Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login failed for user 'sa'..
Why it happens
The container was created with MSSQL_SA_PASSWORD=First-Pass-2026x on the named volume
fix7-mssql-data (container, volume and passwords are the test's own), removed, and
created again on the same volume with Second-Pass-2026x. The master database on the
volume still held the first password: the second one failed, the first one still worked.
The message is vague on purpose. Microsoft's
MSSQLSERVER_18456
page says the text sent to the client "deliberately hides the nature of the authentication
error". The server log keeps it. These lines came from docker logs fix7-mssql after a
wrong password, a login that does not exist and a disabled login:
2026-10-30 02:50:00.88 Logon Error: 18456, Severity: 14, State: 8.
2026-10-30 02:50:00.88 Logon Login failed for user 'sa'. Reason: Password did not match that for the login provided. [CLIENT: 172.17.0.1]
2026-10-30 02:50:01.25 Logon Error: 18456, Severity: 14, State: 5.
2026-10-30 02:50:01.25 Logon Login failed for user 'report_user'. Reason: Could not find a login matching the name provided. [CLIENT: 172.17.0.1]
2026-10-30 02:50:01.75 Logon Error: 18470, Severity: 14, State: 1.
2026-10-30 02:50:01.75 Logon Login failed for user 'report_reader'. Reason: The account is disabled. [CLIENT: 172.17.0.1]
The same page lists the other common states: 7 is a disabled login with a wrong password, 38 a
database that could not be found, 58 a SQL login sent to a server that accepts Windows logins only.
A disabled login with the right password came back as error 18470, and that one does name its
reason to the client. On a server without docker logs, run
EXEC sp_readerrorlog 0, 1, N'Login failed' as an administrator.
LocalDB behaves differently. A SQL login that does not exist returned 18456 with state 5 in its
log, but sa returned error
233, while its log recorded 18456 state 7, "An error occurred while evaluating the password."
The fix
PS> .\FixLab.exe 'Server=127.0.0.1,15433;User ID=sa;Password=First-Pass-2026x;TrustServerCertificate=true' 'ALTER LOGIN sa WITH PASSWORD = ''Second-Pass-2026x'''
OK (-1 row(s) affected) in 0.2 s
PS> .\FixLab.exe 'Server=127.0.0.1,15433;User ID=sa;Password=Second-Pass-2026x;TrustServerCertificate=true' 'SELECT SUSER_SNAME()'
sa
OK (-1 row(s) affected) in 0.2 s
After ALTER LOGIN the password in the compose file and the one on the volume agree.
Keep TrustServerCertificate=true for a local container: without it SqlClient stopped
before the login with the
certificate chain error. Where the server runs on Windows, as LocalDB does, Windows
authentication avoids passwords altogether (the 0 means this LocalDB accepts SQL logins as well):
PS> .\FixLab.exe 'Server=(localdb)\MSSQLLocalDB;Integrated Security=true' 'SELECT SUSER_SNAME(), SERVERPROPERTY(''IsIntegratedSecurityOnly'')'
MACHINE\user | 0
OK (-1 row(s) affected) in 0.4 s
How it was reproduced
A console app from dotnet new console -n FixLab -f net10.0 (.NET SDK 10.0.403) with
Microsoft.Data.SqlClient 7.1.1 runs the SQL in its second argument and prints
Number, Class and State of any SqlException.
The server was mcr.microsoft.com/mssql/server:2022-latest (16.0.4305.5, CU27) published
on 127.0.0.1:15433, plus SQL Server 2022 LocalDB 16.0.1210.3. sqlcmd 16.0.1000.6 on Windows and
the image's own sqlcmd (ODBC Driver 18) gave the same message.
Frequently asked
- What does state 8 mean in SQL Server error 18456?
- The login exists but the password is wrong. The state appears only in the server error log, as Error: 18456, Severity: 14, State: 8. The client always sees state 1.
- Why does my SQL Server Docker container reject the new SA password?
- In this test a new MSSQL_SA_PASSWORD did not change the password on an existing data volume. Connect with the old password and run ALTER LOGIN sa WITH PASSWORD, or remove the volume if its data is disposable.
- How do I see why a SQL Server login failed?
- Read the server error log: docker logs for a container, or EXEC sp_readerrorlog 0, 1, N'Login failed' as an administrator. The Reason text names the cause, such as Password did not match or Could not find a login matching the name provided.
More decoded errors in the Fixes category.