Skip to content

feat(python-setup): widen conflict recovery to generic uv sync (E_PROVISION) failures - #2193

Closed
rugpanov wants to merge 1 commit into
mainfrom
rugpanov/widen-provision-recovery
Closed

rugpanov wants to merge 1 commit into
mainfrom
rugpanov/widen-provision-recovery

Conversation

@rugpanov

Copy link
Copy Markdown
Contributor

What

Widen the Python-setup conflict recovery so a Full-preset run that fails uv sync with a generic E_PROVISION (not only the CLI's provable, pre-sync E_PROVISION_CONFLICT) offers the same recovery: restore the pre-merge pyproject.toml, then Retry as DB Connect setup (--no-constraints).

Why

E_PROVISION_CONFLICT is raised at the merge phase for a direct-pin disjoint (a version pinned in both the user's pyproject.toml and the cluster constraints). Conflicts that only uv's resolver finds — transitive dependencies, or clashes with databricks-connect's own dependency tree — instead fail during the sync as a generic E_PROVISION, and today get no recovery button. The Full tier's pinned cluster deps are the prime suspect for such a failure, so offering the DB-Connect retry (which drops those pins) closes the gap for the motivating "uv sync failed on conflicting versions" users.

How

  • Recovery gate widened from E_PROVISION_CONFLICT to (E_PROVISION_CONFLICT || E_PROVISION) && !skipConstraints && backupPath.
  • Reuses the existing recovery actions verbatim: [Retry as DB Connect setup] + [Open pyproject.toml], with Show Logs hidden (self-service) — identical to the provable-conflict path.
  • Loop-safe: the gate requires the run carried the pins (!skipConstraints), so the --no-constraints retry can never re-enter recovery.
  • Gating on the specific E_PROVISION code (not merely the provision phase) leaves E_PYTHON_INSTALL on its own "Select Python interpreter" remediation.
  • Greenfield projects (no backupPath) fall through to today's handling.

Testing

  • New unit tests: same recovery buttons on a generic E_PROVISION Full failure; the retry re-runs with --no-constraints and adopts the interpreter; no recovery on a pins-dropped (DB Connect) run; no recovery when there is no backup.
  • yarn test:unit (1146 passing) and yarn test:lint both clean.

Notes

  • Telemetry: the widened retry reuses the existing conflict_retry trigger; the preceding failure's errorCode (E_PROVISION vs E_PROVISION_CONFLICT) distinguishes a provable conflict from a suspected one in the funnel.

This pull request and its description were written by Isaac.

*Why*
The "Retry as DB Connect setup" recovery fired only for the CLI's provable,
pre-sync E_PROVISION_CONFLICT (a direct-pin disjoint). Transitive conflicts, and
clashes with databricks-connect's own dependency tree, surface only during
`uv sync` as a generic E_PROVISION and got no recovery affordance -- leaving the
motivating "uv sync failed on conflicting versions" users stuck.

*What*
Widen the recovery gate so a Full-preset run (one that pinned cluster
constraints) that fails provisioning with E_PROVISION -- and carries a pre-merge
backupPath -- offers the same recovery as E_PROVISION_CONFLICT: restore the
pre-merge pyproject.toml, then retry as DB Connect (--no-constraints). Gating on
the specific E_PROVISION code (not just the provision phase) leaves
E_PYTHON_INSTALL on its own "Select Python interpreter" remediation. Loop-safe:
the gate requires the run to have carried the pins (!skipConstraints), so a
--no-constraints retry can never re-enter recovery. Greenfield projects (no
backup) fall through unchanged.

*Verification*
- New unit tests: same recovery buttons on a generic E_PROVISION Full failure;
  the retry re-runs with --no-constraints and adopts; no recovery on a
  pins-dropped run or when there is no backup.
- yarn test:unit (1146 passing) and yarn test:lint both clean.

Co-authored-by: Isaac <no-reply@databricks.com>
@rugpanov
rugpanov deployed to test-trigger-is September 11, 2026 13:07 — with GitHub Actions Active
@rugpanov
rugpanov deployed to test-trigger-is September 11, 2026 13:08 — with GitHub Actions Active
@github-actions

Copy link
Copy Markdown
Contributor

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/vscode

Inputs:

  • PR number: 2193
  • Commit SHA: ca3a1d42e247e9dadedbb4a6fc9d99426e006b34

Checks will be approved automatically on success.

@rugpanov
rugpanov deployed to test-trigger-is September 11, 2026 13:09 — with GitHub Actions Active
@rugpanov

rugpanov commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Integration tests ❌ failed for ca3a1d42.
View run

@rugpanov

Copy link
Copy Markdown
Contributor Author

Closing in favor of a CLI-side fix.

Review of this extension-side widening showed that gating the "Retry as DB Connect" recovery on the generic E_PROVISION code is too coarse. E_PROVISION also covers failures where dropping the cluster pins cannot help: a blocked/unreachable package index (corporate proxy), disk/permission/uv errors, conflicts among the user's own dependencies, and conflicts rooted in databricks-connect's own dependency tree. In the index-unreachable case it would even hide the "Show Logs" button while the message points the user to the logs.

The recovery only resolves failures actually caused by the cluster pins — which is exactly what E_PROVISION_CONFLICT already certifies. The right layer for this is the CLI, which can see uv's resolver output and classify the cause. We'll widen the CLI's E_PROVISION_CONFLICT classification to also cover sync-time conflicts caused by the cluster pins; the extension's existing recovery (already gated on E_PROVISION_CONFLICT) then covers the new cases with no extension change.

Closing this PR; the work moves CLI-side.

@rugpanov rugpanov closed this Sep 14, 2026
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.

1 participant