Skip to main content

ArrowTDS — Troubleshooting

Common failures and their fixes, grouped by where they show up: connecting, authenticating, the licence gate, and querying/ingesting. For the option details referenced here, see CONNECTION.md.


Connection

Connect hangs, then fails after ~30 s. The TCP connect budget (login_timeout, default 30 s) elapsed. When a host resolves to several addresses they share that budget, so this usually means every address is unreachable — a firewall, a wrong port, or the server not listening. Verify with nc -vz <host> 1433. Lower login_timeout to fail faster while diagnosing.

A machine name is much slower than localhost / an IP. The name resolved to several addresses and a leading one (often a link-local fe80:: on Windows) is dropping the SYN. The shared connect budget prevents a flat +30 s stall, but a dead first address still costs time. Connect by IP, or fix DNS/hosts ordering.

Named instance won't connect ("could not determine port for instance …"). Server=host\INSTANCE needs the SQL Server Browser reachable on UDP 1434. Either open UDP 1434 and start the Browser service, or pin the instance to a static port in SQL Server Configuration Manager and connect with an explicit port (Server=host\INSTANCE,54312), which skips the Browser lookup entirely. See CONNECTION.md.

(localdb)\... fails. LocalDB is reached over a named pipe, not TCP — this driver cannot connect to it. Use a full SQL Server (Express is fine).

Azure SQL "Redirect" connection resets. The Redirect gateway policy sends the client to a database node on ports 11000–11999; the driver follows the routing token automatically, but the reconnect needs outbound TCP to 11000–11999. Open that range, or ask your admin to set the server's connection policy to Proxy.

Azure SQL / Fabric: "Server name cannot be determined". The gateway routes on the LOGIN7 server name. This was a driver bug fixed in 0.5.20 — upgrade to ≥ 0.5.20.


TLS / certificates

"certificate verify failed" / hostname mismatch. With encrypt=true the server certificate and hostname are verified by default. For a self-signed dev server, add trust_server_cert=true. Do not use trust_server_cert=true in production — fix the certificate instead. For an IP-literal host, the cert must carry a matching iPAddress SAN.

Azure SQL rejects an unencrypted connection. Azure requires TLS — set encrypt=true (the default-safe path handles SNI + verification).

Windows: driver loads but TLS fails / DLL not found. OpenSSL is not part of Windows. The matching libssl-3-x64.dll / libcrypto-3-x64.dll must sit next to arrowtds_adbc_driver.dll (or the driver must be static-linked). The VC++ runtime (vcruntime140.dll, msvcp140.dll) must also be present.


Authentication

Login failed for user '…'. SQL login credentials are wrong, or the login is disabled / lacks access to the database. Confirm with sqlcmd/SSMS first.

Integrated auth: "Cannot generate SSPI context" / GSSAPI errors. The Kerberos SPN did not match. The driver derives MSSQLSvc/host:<resolved-port> — for a named instance the port is the resolved one. Ensure the SPN is registered for the service account, that you have a valid TGT (klist), and on Linux point at the right credential cache/keytab with krb5.ccache / krb5.keytab. Override the SPN with krb5.spn if needed. Details in AUTHENTICATION.md.

Entra ID: "Federated auth cannot be combined with a password." Remove username/password — federated (token) auth is exclusive and always uses full TLS. Also ensure encrypt=true.

Entra ID: token acquired but "login failed". The identity (user, service principal, or managed identity) must be a database user: CREATE USER [<name>] FROM EXTERNAL PROVIDER. A valid token for a principal with no database mapping still fails login.

auth_type=ActiveDirectory… rejected. Only ActiveDirectoryDefault (the credential chain) is a valid auth_type. For the other Entra modes use the dedicated options: access_token, tenant_id+client_id+client_secret, or managed_identity. See CONNECTION.md.


Licence

Connection fails with an ARROW_LIC_* error. No valid Arpeio licence was found. Supply one via arpeio.adbc.license_file (a .lic path), arpeio.adbc.license (the blob inline), the ARPEIO_ADBC_LICENCE[_FILE] environment variable, or an arpeio_adbc.lic file next to the driver library. The installer's --license flag places the file for you. Full detail — including how to read the current licence state with arpeio.adbc.license.status — is in LICENSING.md.


Query & ingest

Bulk ingest deadlocks or hangs. The DB-API default autocommit=False turns on IMPLICIT_TRANSACTIONS, which can deadlock the single-connection TRUNCATE+INSERT BULK pattern. Open the connection with autocommit=True for ingest. See EXAMPLES.md.

adbc_ingest(mode="create") fails "already exists". The target table exists; the driver returns ALREADY_EXISTS (SQL Server error 2714). Use append, replace, or create_append.

Ingesting XML fails "Invalid column type from bcp client". INSERT BULK does not accept the XML wire type; the driver routes XML via NVARCHAR(MAX) + a cast automatically — if you hit this on an older build, upgrade.

A geospatial column reads as opaque bytes I can't parse. That is geospatial=varbinary (raw CLR-UDT bytes). Use the default geoarrow (or wkb) mode for interoperable output. See DATA_TYPES.md.

Cancelling a long query does nothing. Connection.Cancel / Statement.Cancel return NOT_IMPLEMENTED today — close the statement or connection to abort an in-flight query.


Diagnostics: timing & debug traces

Set these environment variables to see where time goes or to trace the wire. Full list in ENV_VARS.md.

VariableWhat it shows
ARPEIO_ADBC_READ_TIMING=1Per-batch recv_ms / decode_ms / writer_wait_ms on the SELECT stream — tells you whether the wire, the decoder, or downstream backpressure is the bottleneck.
ARROWTDS_TDS_READ_DEBUG=1Verbose per-token TDS read trace (very chatty; wire-protocol bugs only).
ARPEIO_ADBC_QUIET=1Silences the ingest [TDS TIMING] summary and downgrade/row-count warnings.
ARPEIO_ADBC_ALLOCATOR=systemFalls back from mimalloc to libc malloc for decode buffers (if mimalloc misbehaves).

See also