Skip to content

Raise DB-API errors for transport failures and empty access tokens - #961

Open
aminghadersohi wants to merge 2 commits into
databricks:mainfrom
aminghadersohi:fix-transport-errors-and-empty-token
Open

aminghadersohi wants to merge 2 commits into
databricks:mainfrom
aminghadersohi:fix-transport-errors-and-empty-token

Conversation

@aminghadersohi

@aminghadersohi aminghadersohi commented Sep 26, 2026 •

Copy link
Copy Markdown

What type of PR is this?

  • Bug Fix

Description

Problems observed with 4.4.0 and 4.6.0 against a SQL warehouse:

  1. Raw urllib3 errors. When the workspace is unreachable (connection refused, proxy/tunnel failure), ThriftDatabricksClient.make_request re-raised the urllib3 HTTP error of every request except GetOperationStatus unchanged. So connect() and cursor.execute() raised urllib3.exceptions.MaxRetryError, which is not a PEP 249 error. SQLAlchemy therefore does not wrap it in DBAPIError, and callers that handle database errors treat it as an unexpected crash.
  2. Empty token starts a browser login. connect(access_token="") silently dropped the empty token (if access_token:) and fell back to the default interactive U2M OAuth flow. That flow binds a callback server on 127.0.0.1:8020–8024 and blocks until a browser redirect arrives, which on a server means indefinitely. Applications that clear a stale token to trigger their own OAuth flow (and expect the No valid authentication settings! error) hang instead.

Change:

  1. Non-GetOperationStatus urllib3 HTTP errors take the normal non-retryable error path, so they surface as RequestError (OperationalError) with the usual context. urllib3 has already applied its retry policy by then.
  2. An explicitly passed empty access_token is kept. Where the default OAuth login would otherwise start, get_auth_provider raises RuntimeError("No valid authentication settings! access_token is empty"). The same error is raised on the Reyden pre-check path, which skips Thrift for a known Reyden warehouse and would otherwise switch to databricks-oauth. Explicit auth_type, credentials_provider and certificate authentication still take precedence, as they do for a non-empty token; passing no token at all keeps the documented default (databricks-oauth). With use_kernel=True the kernel path already rejects a connection with no credentials (NotSupportedError) and is unchanged.
  3. Changelog entries under # Unreleased.

How is this tested?

  • Unit tests

  • E2E Tests

  • Manually

  • N/A

  • test_make_request_wraps_urllib3_http_error_as_request_error and test_get_python_sql_connector_auth_provider_empty_access_token fail on main and pass with the first commit; test_thrift_backend.py, test_auth.py, test_client.py, test_retry.py and test_session.py passed (285) at that commit.

  • Follow-up tests: test_get_python_sql_connector_auth_provider_empty_access_token_cert_auth and test_known_reyden_empty_access_token_is_rejected. These were not run locally; CI covers them.

  • Both behaviours of the first commit were verified live: through a local CONNECT proxy whose tunnels were cut and then refused, and with access_token="".

Related Tickets & Documents

None.

- ThriftDatabricksClient.make_request re-raised urllib3 HTTP errors of
  every request except GetOperationStatus unchanged, so an unreachable
  workspace (refused connection, proxy/tunnel failure) surfaced from
  connect() and execute() as a raw urllib3 MaxRetryError instead of a
  DB-API error. Report it through the normal non-retryable path as a
  RequestError (OperationalError).
- connect(access_token="") dropped the empty token and fell back to the
  interactive browser OAuth flow, blocking on a local callback server.
  An explicitly empty token now raises 'No valid authentication
  settings!' at once.

Signed-off-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>
Copilot AI lite review requested due to automatic review settings September 26, 2026 09:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Empty-token handling remains inconsistent across OAuth and kernel/recovery paths.

Review effort: Lite
Findings: 1 Low severity

Open (1)
What changed in this PR

This pull request improves DB-API transport error handling and prevents explicitly empty access tokens from silently starting OAuth login flows.

Changes:

  • Wraps transport failures as RequestError.
  • Preserves and rejects explicitly empty access tokens.
  • Adds regression tests for both behaviors.
File Summary
tests/​unit/​test_thrift_backend.py Tests transport-error wrapping.
tests/​unit/​test_auth.py Tests empty-token handling.
src/​databricks/​sql/​client.py Preserves explicitly passed tokens.
src/​databricks/​sql/​backend/​thrift_backend.py Routes transport failures through DB-API handling.
src/​databricks/​sql/​auth/​auth.py Rejects empty access tokens.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/unit/test_thrift_backend.py Outdated
- Keep certificate authentication working when an empty token is passed:
  the empty-token rejection now comes after the cert-auth branch, where
  the default OAuth login would otherwise start.
- Reject an empty token on the Reyden pre-check path too, which skips
  Thrift and previously upgraded the connection to databricks-oauth.
- Remove the duplicate RequestError import in the test.
- Add changelog entries.

Signed-off-by: Amin Ghadersohi <amin.ghadersohi@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants