Skip to content

SEA CreateSession retry ignores RateLimitRetryTimeout / TemporarilyUnavailableRetryTimeout (SDK-internal retry budget) #1573

Open

Description

@eric-wang-1990

Summary

On the SEA path (usethriftclient=0), databricks-jdbc does retry a transient error (429/503) on CreateSession, but the number of retries is fixed by the underlying SDK ApiClient's internal retry policy and is not affected by the JDBC URL params RateLimitRetryTimeout (429) or TemporarilyUnavailableRetryTimeout (503/502/504). Those params are only consulted by the Thrift-path DatabricksHttpRetryHandler, not by the SEA/SDK ApiClient.

Environment

  • driver: databricks-jdbc (OSS) 3.4.x, usethriftclient=0 (SEA)

Behavior

With a perpetual (trigger_count=1000) 429 error injected on CreateSession, opening a connection with two different RateLimitRetryTimeout values yields the same number of CreateSession attempts:

RateLimitRetryTimeout=1  → 4 CreateSession attempts
RateLimitRetryTimeout=10 → 4 CreateSession attempts

Identical result for TemporarilyUnavailableRetryTimeout with a 503 scenario. A longer budget does not produce more retries because the SEA path's retry count comes from com.databricks.sdk.core.ApiClient, which the JDBC layer configures without threading these timeout params into the SDK's retry policy.

Expected

RateLimitRetryTimeout / TemporarilyUnavailableRetryTimeout should govern the SEA retry budget the same way they govern the Thrift path (a longer budget → more retry attempts before giving up) — so an application can bound/extend connection-establishment retries consistently across backends. The cross-driver spec ERRORRECOV-010/012 asserts this "longer timeout → more retries" relationship (C# ADBC honors it on both).

Repro

Cross-driver proxy harness (databricks-driver-test), spec cases ERRORRECOV-010 (429) and ERRORRECOV-012 (503/502/504), SEA mode, sea_create_session_429 / sea_create_session_503 at trigger_count=1000. Committed as xfail tripwires asserting the current no-effect behavior (short == long).

Related

  • databricks-jdbc#1571 — on the Thrift path the same 429/503 on OpenSession does not retry at all without a Retry-After header, so the budget is likewise unobservable there (a different root cause: header-less no-retry vs SDK-internal fixed retry). Together they make ERRORRECOV-010/012 unobservable on both backends today.

Impact

The documented retry-timeout configuration knobs silently have no effect on SEA connection establishment; an operator tuning them for SEA gets no behavior change.

Activity

  1. Jothirmai commented on Oct 16, 2026

    @Jothirmai

    Hi @eric-wang-1990, I'd be interested in investigating this issue and contributing a fix.

    My understanding is that the SEA path delegates "CreateSession" retries to the SDK's "ApiClient", while "RateLimitRetryTimeout" and "TemporarilyUnavailableRetryTimeout" are applied by the JDBC driver's Thrift-path retry handler. As a result, the configured retry budgets are effectively disconnected from SEA connection establishment, even though the same JDBC properties are expected to control retry behavior across both backends.

    Before proposing an implementation, I'd appreciate your guidance on a few design points:

    1. Retry-budget semantics: Should these properties represent a wall-clock time budget for retrying the relevant status codes, with retries continuing until the budget expires, or should the fix preserve the SDK's existing retry policy while making it configurable through these properties?
    2. SDK integration: Is the preferred approach to configure or extend the existing "ApiClient" retry mechanism, or to introduce a JDBC-level retry layer around "CreateSession"? I'd like to avoid duplicating retry logic or accidentally applying retries twice.
    3. Retry behavior: Should the implementation preserve the SDK's existing backoff and "Retry-After" handling while enforcing the JDBC-configured budget?
    4. Regression tests: Would you prefer extending the existing "ERRORRECOV-010" and "ERRORRECOV-012" proxy-harness cases to verify that a longer budget permits additional attempts and that retries stop when the budget expires?

    I also noticed the related #1571 issue on the Thrift path. Since the two paths appear to have different underlying causes, I'd aim to keep this change focused on the SEA retry configuration while ensuring the shared behavior remains consistent.

    I'm happy to trace the relevant code paths, reproduce the behavior locally, and submit a focused PR with regression coverage. If there's an existing implementation direction or any work already planned for this, I'd appreciate your advice before I start.

    Thanks!

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions