Updated and tested 8 October 2026
SQL Server's error messages are unevenly written. Some of them hand you the table, the column and the offending value. Others tell you a connection failed and leave you to work out which of nine things caused it. This page is the list I keep open during an incident, organised by the string you'll paste into a search box, with the cause underneath and the fix after that.
Everything here is grouped by the string the client shows you. Grouping by subsystem would be tidier and less useful, because at the moment you need this page you have a message and nothing else. Where a message deserves its own walkthrough, you get a link to it.
A network-related or instance-specific error occurred while establishing a connection to SQL Server
Cause: the client never completed a TCP connection to the Database Engine. This string is a wrapper, and on its own it's close to useless. The information is in the provider text that follows it, and the number in brackets is what you should search for.
Four inner messages cover most of it. TCP Provider, error: 0 - No such host is known. (Microsoft SQL Server, Error: 11001) is DNS, so the name never resolved. Named Pipes Provider, error: 40 - Could not open a connection to SQL Server (Error: 53) is a network path that wasn't found. TCP Provider: No connection could be made because the target machine actively refused it means you reached the host and nothing was listening on that port. Error 10060, "a connection attempt failed because the connected party did not properly respond after a period of time", is a silent drop, which almost always means a firewall.
Fix: work through enabling remote connections in SQL Server in order, because the order is what saves you time here. Check the service is running before anything else. Then check that TCP/IP is enabled for the instance, and only then argue about the port. The error log prints Server is listening on [ 'any' <ipv4> 1433] at startup and that line settles it. Open the port on the host firewall and on any provider firewall sitting in front of it.
Error Locating Server/Instance Specified
Cause: a named instance lookup failed. The client sent an SSRP datagram to UDP 1434 asking which TCP port host\INSTANCE is on, and no reply came back from SQL Server Browser.
Fix: check the instance name, start the Browser, open UDP 1434 and not TCP 1434, or set a static port and skip the mechanism entirely. For the ordered version with the reasoning attached, see Fixing SQL error 26.
Login failed for user
Cause: the client reached the engine and authentication failed. The client always sees State: 1, which is a placeholder, so the message on your screen cannot tell you why.
Fix: read the real state from the server error log and act on that. Fixing SQL Server error 18456 maps two dozen documented states to their causes, with the T-SQL for each.
Cannot open database "orders" requested by the login. The login failed.
Cause: authentication itself worked. The engine then failed to open the database the connection asked for, either the login's default database or the one named in the connection string. Dropped, renamed, offline, mid-restore or simply a database this login has no user in. The server error log records it as 18456 with state 38, 46 or 126.
Fix: find out what state the database is in first.
SELECT name, state_desc, user_access_desc, is_read_only
FROM sys.databases
ORDER BY name;
ONLINE and MULTI_USER is healthy. RESTORING, OFFLINE, RECOVERY_PENDING or SINGLE_USER is your answer. Naming a database explicitly in the SQL Server connection string does not rescue you here, because several drivers open the login's default database first regardless. Repoint it with ALTER LOGIN [appuser] WITH DEFAULT_DATABASE = [master]; if the database itself is healthy and only the pointer is stale, then fix the user mapping properly.
The server principal is not able to access the database under the current security context
Cause: error 916. The login connects to the instance without trouble and then has no user in the target database, and the guest user has no CONNECT permission there. You'll meet it most often in SSMS Object Explorer, where expanding Databases enumerates every database on the server including ones your login can't touch.
Fix: create a user for that login in that database and give it a role. Microsoft's page for error 916 also lists GRANT CONNECT TO guest; and ALTER DATABASE ... SET TRUSTWORTHY ON; as options. I'd treat both as things to understand and not things to run: granting CONNECT to guest opens that database to every login on the server, and TRUSTWORTHY is a security posture decision that happens to make an error go away.
The certificate chain was issued by an authority that is not trusted
Cause: your driver now encrypts by default and your server is presenting the self-signed certificate it generated at install time. Every major driver flipped this within a few years of each other. Microsoft.Data.SqlClient changed Encrypt to true by default in version 4.0, ODBC Driver 18 changed Encrypt from no to yes, and the JDBC driver made the same change in version 10.2 and called it a breaking change. Nothing changed on your server. The change is in your client library.
Fix: install a certificate the client trusts. On Linux that's two mssql-conf keys and a restart:
sudo /opt/mssql/bin/mssql-conf set network.tlscert /etc/ssl/certs/mssql.pem
sudo /opt/mssql/bin/mssql-conf set network.tlskey /etc/ssl/private/mssql.key
sudo systemctl restart mssql-server
For a lab or a throwaway container, TrustServerCertificate=True in the connection string, or -C on sqlcmd, gets you moving. There is a limit to that trick. With Encrypt=Strict (TDS 8.0) in Microsoft.Data.SqlClient 5.0 and later, TrustServerCertificate is ignored and the certificate is validated regardless.
sqlcmd: command not found
Cause: mssql-tools18 puts sqlcmd and bcp in /opt/mssql-tools18/bin, which is outside the default PATH, and nothing adds it to your shell for you.
Fix: install the package, then put the directory on PATH for good.
sudo apt-get install mssql-tools18 unixodbc-dev
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc
source ~/.bashrc
sqlcmd -S localhost -U sa -P '<password>' -C
The full package sequence lives in the SQL Server on Ubuntu install guide. Note the -C on that last line. In mssql-tools18 the -N encryption option defaults to mandatory, which Microsoft calls out as "a breaking change from SQL Server 2022 (16.x) and earlier versions, where the default is -No", so a command that worked on an older box now fails on a self-signed certificate until you trust it with -C or make encryption optional with -No.
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Cause: one string, two completely different failures, and telling them apart is most of the work. The connection timeout defaults to 15 seconds in Microsoft.Data.SqlClient and fires while the driver is still trying to reach the server. The command timeout defaults to 30 seconds and fires on a query that started fine and never finished.
Fix: if it trips at roughly 15 seconds with no query running, treat it as a network or discovery problem and work the first section of this page. If it trips at roughly 30 seconds mid-query, go looking for blocking:
SELECT session_id, blocking_session_id, wait_type, wait_time, status, command
FROM sys.dm_exec_requests
WHERE blocking_session_id <> 0;
Raising the number is a workaround, and I'd rather fix the plan or the blocker. Microsoft does document one legitimate increase, recommending a connection timeout of at least 30 seconds for Azure SQL Database. Setting CommandTimeout to 0 means wait forever, which is defensible in a nightly job and indefensible in a web request.
String or binary data would be truncated
Cause: a value is longer than the column you're writing it into. Error 8152, and for twenty years it refused to say which column.
Fix: get the better message. SQL Server 2019 introduced error 2628, "String or binary data would be truncated in table '%.*ls', column '%.*ls'. Truncated value: '%.*ls'.", which names the table, the column and the value that didn't fit. It's controlled by a database scoped configuration that defaults to ON:
ALTER DATABASE SCOPED CONFIGURATION SET VERBOSE_TRUNCATION_WARNINGS = ON;
A database restored from an older server keeps its old compatibility level through the upgrade, so a brand new SQL Server 2025 instance will happily serve you the useless 8152 forever. At compatibility level 140 or lower you need trace flag 460 instead. Check with SELECT name, compatibility_level FROM sys.databases; before you conclude the feature is broken, because the whole thing only switches on at database compatibility level 150 or higher.
Could not allocate space for object ... because the 'PRIMARY' filegroup is full
Cause: error 1105, and the full text names all the possibilities: "because the '%.*ls' filegroup is full due to lack of storage space or database files reaching the maximum allowed size. Note that UNLIMITED files are still limited to 16TB." So it's the disk, autogrowth being off, a file that hit its MAXSIZE or an edition cap.
Fix: check which of those it is before you touch anything, because adding a data file to a database that's out of disk helps nobody.
SELECT name, type_desc, size / 128.0 AS size_mb, max_size, growth, is_percent_growth
FROM sys.database_files;
A max_size of -1 is unlimited, 0 means no growth and anything else is a page count you've hit. Microsoft's page for error 1105 lists the actions from there: turn on autogrow, add a file to the filegroup or drop indexes and tables you no longer need. One odd case documented on the same page: when an index spans several files and one of them is full, ALTER INDEX REORGANIZE can raise 1105 where ALTER INDEX REBUILD succeeds.
The Express and Developer edition comparison carries the current per-edition numbers, and on Express the cap is the first thing to check. The limit on the maximum relational database size moved from 10 GB in SQL Server 2022 and earlier to 50 GB in SQL Server 2025, so half the advice online about this is a version behind.
The transaction log for database '...' is full
Cause: error 9002, and the message itself tells you where to look: "To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases." Something is holding the log open and stopping truncation, so adding space to the file will not clear the error.
Fix: ask the column the error points at.
SELECT name, recovery_model_desc, log_reuse_wait_desc
FROM sys.databases
WHERE name = 'orders';
LOG_BACKUP means the database is in FULL recovery and nobody is taking log backups. ACTIVE_TRANSACTION means an open transaction is pinning the log, and DBCC OPENTRAN will find it. AVAILABILITY_REPLICA or REPLICATION point at a synchronisation that isn't completing. Growing the log file does not clear the condition.
The instance of the SQL Server Database Engine cannot obtain a LOCK resource
Cause: error 1204. Locks come from a pool of lock structures and the pool ran out. The lock manager can't use more than 60% of available SQL Server memory, so you get here through memory pressure, through a locks setting that was pinned to a non-default value with sp_configure years ago or through trace flags 1211 or 1224 disabling lock escalation while a query tries to take millions of row locks.
Fix: find the session hoarding them.
SELECT request_session_id, COUNT (*) num_locks
FROM sys.dm_tran_locks
GROUP BY request_session_id
ORDER BY count (*) DESC;
Then the choice is killing the session or fixing the statement behind it, and a huge single-statement DELETE or UPDATE is the usual culprit. Batch it into chunks of a few thousand rows and the problem disappears. Reset a pinned lock configuration back to dynamic with EXEC sp_configure 'locks', 0;, and check trace flags 1211 and 1224, which Microsoft's error 1204 page names as contributors. I have hit 1204 twice and both times it was that same shape of DELETE, so what I know about the trace flag path comes from the documentation.
Job for mssql-server.service failed, or SQL Server on Linux won't start
Cause: systemd reports the failure and tells you almost nothing. The real reason is usually a setting in /var/opt/mssql/mssql.conf that the engine can't honour, a memory limit set below what the instance needs, permissions on /var/opt/mssql that no longer let the mssql user write or a data directory on a file system SQL Server won't use. That last one catches people building custom mounts: the supported file systems are XFS and ext4, and Microsoft's requirements table names BTRFS as unsupported.
Fix: get the status, then get the log, in that order.
systemctl status mssql-server --no-pager
sudo iconv -f UTF-16LE -t UTF-8 /var/opt/mssql/log/errorlog -o /tmp/errorlog.txt
tail -40 /tmp/errorlog.txt
The error log is UTF-16LE, so reading it raw gives you spaced-out nonsense and people conclude the file is corrupt. It isn't. If a configuration setting is what's blocking startup, bring the engine up in minimal configuration mode to get in and undo it:
sudo -u mssql /opt/mssql/bin/sqlservr -f
A failed or half-finished initial setup is the other common case, and rerunning it is safe:
sudo systemctl stop mssql-server
sudo /opt/mssql/bin/mssql-conf setup
sudo systemctl start mssql-server

