Skip to content

Fix transpile hanging with incomplete config in non-interactive mode#2326

Open
moomindani wants to merge 2 commits intodatabrickslabs:mainfrom
moomindani:fix/2086-transpile-hang-incomplete-config
Open

Fix transpile hanging with incomplete config in non-interactive mode#2326
moomindani wants to merge 2 commits intodatabrickslabs:mainfrom
moomindani:fix/2086-transpile-hang-incomplete-config

Conversation

@moomindani
Copy link

@moomindani moomindani commented Mar 9, 2026

Summary

Fixes #2086.

When databricks labs lakebridge transpile is run with missing required configuration (e.g. no --input-source), the checker falls back to prompting the user via input(). However, the Databricks CLI intercepts stdin for the transpile command because it expects a JSON summary written to stdout — so the input() call blocks forever with no output or error message. The user has to ^C to escape.

Stack trace from the issue showing where it hangs:

File ".../cli.py", line 235, in _prompt_input_source
    prompted_input_source = self._prompts.question("Enter input SQL path (directory/file)").strip()
File ".../tui.py", line 125, in question
    res = input(prompt)  # <-- hangs here
KeyboardInterrupt

Root cause

_TranspileConfigChecker uses Prompts.question() / Prompts.choice() as a fallback whenever a required configuration value is absent. These methods call input() which blocks on stdin. When the Databricks CLI runs transpile non-interactively, stdin is not connected to the user's terminal, so the call hangs indefinitely.

Fix

  • Add _is_interactive: bool to _TranspileConfigChecker (defaults to sys.stdin.isatty(), injectable via is_interactive kwarg for testing).
  • Add _require_interactive(msg): raises a descriptive ValueError immediately if not in a TTY — before any input() is reached.
  • Call _require_interactive() before each of the 5 prompt sites:
Prompt site Non-interactive error message
--input-source missing "Missing required value for '--input-source': use '--input-source' to specify..."
--output-folder missing "Missing required value for '--output-folder': use '--output-folder' to specify..."
Multiple dialects available "Multiple source dialects are available: use '--source-dialect' to specify one of: ..."
Multiple transpilers for dialect "Multiple transpilers are available for dialect X: use '--transpiler-config-path'..."
Required transpiler option missing "Missing required transpiler option 'X': use '--target-technology' to provide it." (or install-transpile if no CLI arg exists)
  • Add _TRANSPILER_OPTION_CLI_ARGS class-level constant mapping known transpiler option flags to their CLI argument names (overrides-file--overrides-file, target-tech--target-technology).
  • Remove the pre-existing TODO comment in _handle_missing_transpiler_option (addressed by this PR).

Changes to existing tests

Two existing tests used MockPrompts to simulate interactive prompting and previously passed locally only because a developer terminal has a TTY (sys.stdin.isatty()True). They would silently fail in CI:

  • mock_cli_transpile_no_config fixture: uses MockPrompts to answer dialect/path prompts → patched isatty=True.
  • test_transpile_prints_errors: uses MockPrompts to answer an experimental option prompt → patched isatty=True.

New tests

Test What it covers
test_transpile_non_interactive_missing_input_source Raises when --input-source absent
test_transpile_non_interactive_missing_output_folder Raises when --output-folder absent
test_transpile_non_interactive_missing_source_dialect_with_multiple_dialects Raises when dialect must be chosen from multiple options
test_transpile_non_interactive_missing_required_transpiler_option_with_cli_arg Raises with correct --target-technology hint when target-tech option is absent

🤖 Generated with Claude Code

…atabrickslabs#2086)

When `transpile` is run without required configuration values and stdin is not
a TTY (e.g. when driven by the Databricks CLI), the code previously fell
through to `input()` which hung indefinitely because the Databricks CLI
intercepts stdin.

Add `_is_interactive` to `_TranspileConfigChecker` (defaults to
`sys.stdin.isatty()`) and a `_require_interactive()` guard that raises a
clear `ValueError` before each prompt call when not running interactively.
This covers: `--input-source`, `--output-folder`, `--source-dialect` (when
multiple dialects are available), `--transpiler-config-path` (when multiple
transpilers match a dialect), and missing required transpiler options.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ARGS

Avoids recreating the dict on every call to _handle_missing_transpiler_option.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 93.75000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 66.46%. Comparing base (7ff77c2) to head (fd4dd2c).

Files with missing lines Patch % Lines
src/databricks/labs/lakebridge/cli.py 93.75% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2326      +/-   ##
==========================================
+ Coverage   66.41%   66.46%   +0.04%     
==========================================
  Files          99       99              
  Lines        9094     9110      +16     
  Branches      974      976       +2     
==========================================
+ Hits         6040     6055      +15     
- Misses       2878     2879       +1     
  Partials      176      176              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

[BUG]: Running transpile with incomplete configuration hangs

1 participant