Skip to content

Binary() call returns plain bytes instead of DB-API type object, causes implicit conversion errors #512

@capnsue

Description

@capnsue

Describe the bug

A clear and concise description of what the bug is.

If you are seeing an exception, include the full exceptions details (message and stack trace).

mssql_python.Binary() returns the input bytes object unchanged, with no type wrapping. As a result, the driver cannot distinguish binary data from a string at parameter bind time and sends it as varchar. Attempting to insert into a varbinary(max) column then fails with a SQL Server implicit conversion error.

Per PEP 249 (DB-API 2.0), Binary() is required to be a type constructor that produces an object the driver recognizes as binary, not the raw python bytes type itself

  [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Implicit conversion from data type                                                                                                                                                                                                         
  varchar to varbinary(max) is not allowed. Use the CONVERT function to run this query.

  mssql_python.exceptions.ProgrammingError: Driver Error: Syntax error or access violation;                                                                                                                                                                                                          
  DDBC Error: [Microsoft][SQL Server]Implicit conversion from data type varchar to                                                                                                                                                                                                                   
  varbinary(max) is not allowed. Use the CONVERT function to run this query.

To reproduce

Include a complete code listing (or project/solution) that we can run to reproduce the issue.

Partial code listings, or multiple fragments of code, will slow down our response or cause us to push the issue back to you to provide code to reproduce the issue.

import mssql_python                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                   
  # Binary() should return a typed wrapper, not plain bytes
  assert type(mssql_python.Binary(b"hello")) is bytes  # passes -- this is the bug
                                                                                                                                                                                                                                                                                                     
  # Full reproduction: insert bytes into a varbinary(max) column                                                                                                                                                                                                                                     
  conn = mssql_python.connect("your_connection_string")                                                                                                                                                                                                                                              
  cursor = conn.cursor()                                                                                                                                                                                                                                                                             
  cursor.execute("CREATE TABLE #test (data varbinary(max))")                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                                                                     
  data = b"hello world"                                                                                                                                                                                                                                                                            
  wrapped = mssql_python.Binary(data)                                                                                                                                                                                                                                                                
  cursor.execute("INSERT INTO #test VALUES (?)", (wrapped,))                                                                                                                                                                                                                                       
  # Raises: Implicit conversion from data type varchar to varbinary(max) is not allowed

Expected behavior

mssql_python.Binary(b"hello") should return an object that the driver recognizes as binary data at parameter bind time, causing it to be sent with the correct SQL type so that insertion into varbinary(max) columns succeeds without requiring explicit CONVERT in the query.

perhaps an implementation of this could look like:

class Binary(bytes):
   pass

so that it can be checked at bind time

Further technical details

Python version: 3.14.3
SQL Server version: (e.g. SQL Server 2022) 2025
Operating system: Windows 10 (build 26100)

Additional context
Workaround: pass the bytes as a hex string and use CONVERT(varbinary(max), ?, 2) in the SQL (style 2 = hex without 0x prefix). This is effective but requires callers to work around a driver limitation that PEP 249 says should be handled transparently.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage neededFor new issues, not triaged yet.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions