The mssql-python driver defines a standard exception hierarchy, common error handling patterns, and SQLSTATE code mappings for SQL Server and Azure SQL.
Exception hierarchy
The mssql-python driver follows the DB-API 2.0 (PEP 249) exception hierarchy:
Exception (builtins)
├── Warning
└── Error
├── InterfaceError
└── DatabaseError
├── DataError
├── OperationalError
├── IntegrityError
├── InternalError
├── ProgrammingError
└── NotSupportedError
ConnectionStringParseError (standalone, not part of hierarchy)
Exception descriptions
Catch the most specific exception that matches your situation. For example, catch IntegrityError for constraint violations on INSERT/UPDATE operations, and ProgrammingError for SQL syntax issues during development. Catch the base Error class only as a fallback.
| Exception |
When raised |
Warning |
Non-fatal warnings from the database. |
Error |
Base class for all database errors. |
InterfaceError |
Errors related to the database interface (driver), not the database itself. |
DatabaseError |
Errors related to the database. |
DataError |
Errors due to problems with processed data (division by zero, value out of range). |
OperationalError |
Errors related to database operation (connection lost, memory allocation, transaction errors). |
IntegrityError |
Errors when database integrity is affected (foreign key violation, unique constraint). |
InternalError |
Internal database errors (cursor not valid, transaction out of sync). |
ProgrammingError |
Programming errors (syntax errors, table not found, wrong number of parameters). |
NotSupportedError |
Feature not supported by the database or driver. |
ConnectionStringParseError |
Invalid connection string syntax or unknown keywords. |
Basic error handling
Use try-except blocks to handle database errors:
import mssql_python
try:
conn = mssql_python.connect(connection_string)
cursor = conn.cursor()
cursor.execute("INSERT INTO Production.Product (Name) VALUES (%(name)s)", {"name": "Test"})
conn.commit()
except mssql_python.IntegrityError as e:
print(f"Constraint violation: {e}")
conn.rollback()
except mssql_python.ProgrammingError as e:
print(f"SQL syntax error: {e}")
except mssql_python.OperationalError as e:
print(f"Connection or operational error: {e}")
except mssql_python.Error as e:
print(f"Database error: {e}")
finally:
if 'conn' in locals():
conn.close()
Access exceptions through the connection
You can catch exceptions through the connection instance:
try:
cursor.execute("INVALID SQL")
except conn.ProgrammingError as e:
print(f"Caught via connection: {e}")
Error message structure
mssql-python exception objects expose three attributes that come from the driver's Exception base class:
| Attribute |
Source |
Description |
driver_error |
Python driver |
Standardized English text chosen by the SQLSTATE returned from ODBC (for example, "Communication link failure", "Invalid authorization specification", "Syntax error or access violation"). Stable across releases; safe to substring-match. |
ddbc_error |
Direct Database Connectivity (DDBC) |
The server-side message, typically prefixed with [Microsoft][SQL Server]. Format isn't a stable contract. |
message |
Composed |
f"Driver Error: {driver_error}; DDBC Error: {ddbc_error}". This is what str(exc) returns. |
try:
cursor.execute("SELECT * FROM no_such_table;")
except mssql_python.ProgrammingError as exc:
print(exc.driver_error) # Base table or view not found
print(exc.ddbc_error) # [Microsoft][SQL Server]Invalid object name 'no_such_table'.
print(exc) # Driver Error: Base table or view not found; DDBC Error: ...
The SQL Server engine error number (such as 208 or 40501) isn't exposed as an attribute and isn't reliably embedded in either string. Classify errors by exception subclass plus driver_error text. For Azure SQL throttling, see Retry logic.
SQLSTATE classification
mssql-python uses the SQLSTATE returned by ODBC to choose both the Python exception subclass and the driver_error text. The full SQLSTATE → exception mapping is in exceptions.py in the driver source. The next section lists the SQLSTATEs that appear most often with SQL Server and Azure SQL.
Connection errors
Connection failures from mssql_python.connect() raise mssql_python.OperationalError, the same as other connectivity failures:
import mssql_python
try:
conn = mssql_python.connect(
"Server=unreachable-server.database.windows.net;"
"Database=<database>;"
"Authentication=ActiveDirectoryDefault;"
"Encrypt=yes"
)
except mssql_python.OperationalError as e:
print(f"Connection failed: {e.driver_error}")
# e.driver_error: "Client unable to establish connection"
Connection string errors
Connection string parsing errors raise ConnectionStringParseError:
try:
conn = mssql_python.connect("Servr=localhost;") # Typo
except mssql_python.ConnectionStringParseError as e:
print(f"Invalid connection string: {e}")
# Output: Unknown keyword 'Servr'
SQLSTATE code reference
SQLSTATE codes are five-character codes that identify error conditions. The first two characters indicate the class, and the last three indicate the subclass. You rarely need to inspect these codes directly. Instead, catch the appropriate Python exception type (listed in the "Exception" column). Use SQLSTATE codes when you need to distinguish between specific error conditions within the same exception type, for example to differentiate a deadlock (40001) from a general connection failure (08S01).
Class 00 - Successful completion
| SQLSTATE |
Exception |
Description |
| 00000 |
None |
Success |
Class 01 - Warning
| SQLSTATE |
Exception |
Description |
| 01000 |
Warning |
General warning |
| 01001 |
Warning |
Cursor operation conflict |
| 01002 |
Warning |
Disconnect error |
| 01003 |
DataError |
NULL value eliminated in set function |
| 01004 |
DataError |
String data, right truncation |
| 01006 |
Warning |
Privilege not revoked |
| 01007 |
Warning |
Privilege not granted |
| 01S00 |
Warning |
Invalid connection string attribute |
| 01S01 |
Warning |
Error in row |
| 01S02 |
Warning |
Option value changed |
Class 07 - Dynamic SQL error
| SQLSTATE |
Exception |
Description |
| 07001 |
ProgrammingError |
Wrong number of parameters |
| 07002 |
ProgrammingError |
COUNT field incorrect |
| 07005 |
ProgrammingError |
Prepared statement not a cursor-specification |
| 07006 |
ProgrammingError |
Restricted data type attribute violation |
| 07009 |
ProgrammingError |
Invalid descriptor index |
| 07S01 |
ProgrammingError |
Invalid use of default parameter |
Class 08 - Connection exception
| SQLSTATE |
Exception |
Description |
| 08001 |
OperationalError |
Client unable to establish connection |
| 08002 |
OperationalError |
Connection name in use |
| 08003 |
OperationalError |
Connection does not exist |
| 08004 |
OperationalError |
Server rejected the connection |
| 08007 |
OperationalError |
Connection failure during transaction |
| 08S01 |
OperationalError |
Communication link failure |
Class 21 - Cardinality violation
| SQLSTATE |
Exception |
Description |
| 21S01 |
ProgrammingError |
Insert value list does not match column list |
| 21S02 |
ProgrammingError |
Degree of derived table does not match column list |
Class 22 - Data exception
| SQLSTATE |
Exception |
Description |
| 22001 |
DataError |
String data, right truncation |
| 22002 |
DataError |
Indicator variable required but not supplied |
| 22003 |
DataError |
Numeric value out of range |
| 22007 |
DataError |
Invalid datetime format |
| 22008 |
DataError |
Datetime field overflow |
| 22012 |
DataError |
Division by zero |
| 22015 |
DataError |
Interval field overflow |
| 22018 |
DataError |
Invalid character value for cast specification |
| 22019 |
DataError |
Invalid escape character |
| 22025 |
DataError |
Invalid escape sequence |
| 22026 |
DataError |
String data, length mismatch |
Class 23 - Integrity constraint violation
| SQLSTATE |
Exception |
Description |
| 23000 |
IntegrityError |
Integrity constraint violation (general) |
Class 24 - Invalid cursor state
| SQLSTATE |
Exception |
Description |
| 24000 |
InternalError |
Invalid cursor state |
Class 25 - Invalid transaction state
| SQLSTATE |
Exception |
Description |
| 25000 |
OperationalError |
Invalid transaction state |
| 25S01 |
OperationalError |
Transaction state unknown |
| 25S02 |
OperationalError |
Transaction is still active |
| 25S03 |
OperationalError |
Transaction is rolled back |
Class 28 - Invalid authorization specification
| SQLSTATE |
Exception |
Description |
| 28000 |
OperationalError |
Invalid authorization specification (login failed) |
Class 34 - Invalid cursor name
| SQLSTATE |
Exception |
Description |
| 34000 |
ProgrammingError |
Invalid cursor name |
Class 3C - Duplicate cursor name
| SQLSTATE |
Exception |
Description |
| 3C000 |
ProgrammingError |
Duplicate cursor name |
Class 3D - Invalid catalog name
| SQLSTATE |
Exception |
Description |
| 3D000 |
ProgrammingError |
Invalid catalog name |
Class 3F - Invalid schema name
| SQLSTATE |
Exception |
Description |
| 3F000 |
ProgrammingError |
Invalid schema name |
Class 40 - Transaction rollback
| SQLSTATE |
Exception |
Description |
| 40001 |
OperationalError |
Serialization failure (deadlock) |
| 40002 |
OperationalError |
Integrity constraint violation caused rollback |
| 40003 |
OperationalError |
Statement completion unknown |
Class 42 - Syntax error or access rule violation
| SQLSTATE |
Exception |
Description |
| 42000 |
ProgrammingError |
Syntax error or access violation |
| 42S01 |
ProgrammingError |
Base table or view already exists |
| 42S02 |
ProgrammingError |
Base table or view not found |
| 42S11 |
ProgrammingError |
Index already exists |
| 42S12 |
ProgrammingError |
Index not found |
| 42S21 |
ProgrammingError |
Column already exists |
| 42S22 |
ProgrammingError |
Column not found |
Class 44 - WITH CHECK OPTION violation
| SQLSTATE |
Exception |
Description |
| 44000 |
IntegrityError |
WITH CHECK OPTION violation |
Class HY - CLI-specific condition
| SQLSTATE |
Exception |
Description |
| HY000 |
DatabaseError |
General error |
| HY001 |
OperationalError |
Memory allocation error |
| HY003 |
ProgrammingError |
Invalid application buffer type |
| HY004 |
ProgrammingError |
Invalid SQL data type |
| HY007 |
ProgrammingError |
Associated statement is not prepared |
| HY008 |
OperationalError |
Operation canceled |
| HY009 |
ProgrammingError |
Invalid use of null pointer |
| HY010 |
ProgrammingError |
Function sequence error |
| HY011 |
ProgrammingError |
Attribute cannot be set now |
| HY012 |
ProgrammingError |
Invalid transaction operation code |
| HY013 |
OperationalError |
Memory management error |
| HY014 |
OperationalError |
Limit on number of handles exceeded |
| HY015 |
ProgrammingError |
No cursor name available |
| HY016 |
ProgrammingError |
Cannot modify an implementation row descriptor |
| HY017 |
ProgrammingError |
Invalid use of automatically allocated descriptor handle |
| HY018 |
OperationalError |
Server declined cancel request |
| HY019 |
ProgrammingError |
Non-character and non-binary data sent in pieces |
| HY020 |
DataError |
Attempt to concatenate a null value |
| HY021 |
ProgrammingError |
Inconsistent descriptor information |
| HY024 |
ProgrammingError |
Invalid attribute value |
| HY090 |
ProgrammingError |
Invalid string or buffer length |
| HY091 |
ProgrammingError |
Invalid descriptor field identifier |
| HY092 |
ProgrammingError |
Invalid attribute/option identifier |
| HY095 |
ProgrammingError |
Function type out of range |
| HY096 |
ProgrammingError |
Invalid information type |
| HY097 |
ProgrammingError |
Column type out of range |
| HY098 |
ProgrammingError |
Scope type out of range |
| HY099 |
ProgrammingError |
Nullable type out of range |
| HY100 |
ProgrammingError |
Uniqueness option type out of range |
| HY101 |
ProgrammingError |
Accuracy option type out of range |
| HY103 |
ProgrammingError |
Invalid retrieval code |
| HY104 |
ProgrammingError |
Invalid precision or scale value |
| HY105 |
ProgrammingError |
Invalid parameter type |
| HY106 |
ProgrammingError |
Fetch type out of range |
| HY107 |
ProgrammingError |
Row value out of range |
| HY109 |
ProgrammingError |
Invalid cursor position |
| HY110 |
ProgrammingError |
Invalid driver completion |
| HY111 |
ProgrammingError |
Invalid bookmark value |
| HYC00 |
NotSupportedError |
Optional feature not implemented |
| HYT00 |
OperationalError |
Timeout expired |
| HYT01 |
OperationalError |
Connection timeout expired |
Class IM - Driver manager error
| SQLSTATE |
Exception |
Description |
| IM001 |
InterfaceError |
Driver does not support this function |
| IM002 |
InterfaceError |
Data source name not found |
| IM003 |
InterfaceError |
Specified driver could not be loaded |
| IM004 |
InterfaceError |
Driver's SQLAllocHandle on SQL_HANDLE_ENV failed |
| IM005 |
InterfaceError |
Driver's SQLAllocHandle on SQL_HANDLE_DBC failed |
| IM006 |
InterfaceError |
Driver's SQLSetConnectAttr failed |
| IM007 |
InterfaceError |
No data source or driver specified |
| IM008 |
InterfaceError |
Dialog failed |
| IM009 |
InterfaceError |
Unable to load translation DLL |
| IM010 |
InterfaceError |
Data source name too long |
| IM011 |
InterfaceError |
Driver name too long |
| IM012 |
InterfaceError |
DRIVER keyword syntax error |
| IM014 |
InterfaceError |
Invalid DSN |
| IM015 |
InterfaceError |
Corrupt file data source |
Common SQL Server error numbers
Beyond SQLSTATE, SQL Server provides native error numbers in parentheses. These are the errors you're most likely to encounter in application code. Build retry logic around error 1205 (deadlock) and transient connection errors (see Retry logic).
| Error |
Message pattern |
Resolution |
| 208 |
Invalid object name |
Verify that the table or view exists and check schema qualification. |
| 547 |
Constraint violation |
A foreign key or check constraint failed. |
| 2627 |
Unique constraint violation |
A duplicate key value was inserted. |
| 2601 |
Unique index violation |
A duplicate key exists in the index. |
| 4060 |
Cannot open database |
The database doesn't exist or access is denied. |
| 18456 |
Login failed |
Authentication failure. Check credentials. |
| 1205 |
Deadlock victim |
The transaction was rolled back. Retry the operation. |
Symptom-to-exception quick reference
Use this table to map common symptoms to the exception type you should catch:
| Symptom |
Exception |
Likely cause |
| "Login failed for user" |
OperationalError |
Wrong credentials or user not mapped to database. |
| "Client unable to establish connection" |
OperationalError |
Server unreachable, firewall, or DNS issue. |
| "Timeout expired" |
OperationalError |
Query or connection timeout. Increase timeout or optimize query. |
| "Invalid object name" |
ProgrammingError |
Table doesn't exist or schema not specified. |
| "Incorrect syntax" |
ProgrammingError |
SQL syntax error. Test query in SSMS. |
| "Wrong number of parameters" |
ProgrammingError |
Parameter count doesn't match placeholders. |
| "Violation of PRIMARY KEY" |
IntegrityError |
Duplicate key. Use MERGE or check before inserting. |
| "Violation of FOREIGN KEY" |
IntegrityError |
Referenced row doesn't exist. Insert parent first. |
| "Transaction was deadlocked" |
OperationalError (error 1205) |
Lock contention. Implement retry logic. |
| "String or binary data would be truncated" |
DataError |
Value exceeds column length. Check data or increase column size. |
| "Conversion failed" |
DataError |
Type mismatch. Use the correct Python type for the column. |
| "Unknown keyword" |
ConnectionStringParseError |
Typo in connection string keyword. |
| "callproc is not supported" |
NotSupportedError |
Use cursor.execute("EXECUTE ...") instead. |
Best practices
- Catch specific exceptions before generic ones. Order from most specific (
IntegrityError) to least specific (Error).
- Always handle IntegrityError for data modification operations. Constraint violations are expected in normal operation (for example, a user trying to create a duplicate username).
- Log the full error context for troubleshooting. The exception exposes
driver_error (stable, SQLSTATE-derived text) and ddbc_error (server-side message). Log both; classify on driver_error.
- Implement retry logic for transient errors (connection failures, deadlocks). See Retry logic.
- Use rollback() in exception handlers to clean up failed transactions. Without explicit rollback, the connection remains in a failed transaction state.
Related content