Visitar URL original
Model final command errors explicitly by zanieb · Pull Request #20188 · astral-sh/uv · GitHub
Skip to content

Model final command errors explicitly - #20188

Merged
zanieb merged 1 commit into
mainfrom
zb/explicit-user-failures
Jul 7, 2026
Merged

zanieb merged 1 commit into
mainfrom
zb/explicit-user-failures

Conversation

@zanieb

@zanieb zanieb commented Jul 7, 2026 •

Copy link
Copy Markdown
Member

Keep ExitStatus code-only and represent propagated command errors explicitly as UvError::User or UvError::Unexpected. Command handlers classify and propagate their errors; the entrypoint renders user errors as a single line with exit code 1 and renders unclassified error chains with exit code 2. This preserves the existing default text and exit codes while providing a behavior-focused alternative to the error-carrying ExitStatus introduced in #20114.

The stacked follow-up #20163 routes this centralized rendering through Printer and defines the resulting -q and -qq behavior.

Part of #17110.

@zanieb
zanieb force-pushed the zb/explicit-user-failures branch from d625418 to 34ea105 Compare July 7, 2026 15:09
@zanieb
zanieb force-pushed the zb/explicit-user-failures branch from 34ea105 to 3789bd8 Compare July 7, 2026 15:26
@zanieb zanieb changed the title Model final command failures explicitly Model final command errors explicitly Jul 7, 2026
Comment thread crates/uv/src/commands/project/sync.rs Resolved
@zanieb
zanieb force-pushed the zb/explicit-user-failures branch 2 times, most recently from bf5c297 to 63f741c Compare July 7, 2026 15:43
@zanieb
zanieb changed the base branch from charlie/operation-diagnostic-printer to main July 7, 2026 15:43
@astral-sh-bot

astral-sh-bot Bot commented Jul 7, 2026 •

Copy link
Copy Markdown

uv test inventory changes

This PR changes the tests when compared with the latest main baseline.

  • Added tests: 0
  • Removed tests: 2
  • Changed suites: 1
uv-shell: +0 / -2

Added: none

Removed:

  • uv-shell::shlex::tests::escape_posix_borrows_unchanged_strings
  • uv-shell::tests::shell_escape_borrows_unchanged_strings

@zanieb
zanieb marked this pull request as ready for review July 7, 2026 17:10
@zanieb
zanieb force-pushed the zb/explicit-user-failures branch from 4320d74 to c3b9f91 Compare July 7, 2026 17:42
@zanieb
zanieb merged commit da1613b into main Jul 7, 2026
57 checks passed
@zanieb
zanieb deleted the zb/explicit-user-failures branch July 7, 2026 18:38
@zanieb zanieb added the internal A refactor or improvement that is not user-facing label Jul 7, 2026
zanieb added a commit that referenced this pull request Jul 7, 2026
Render final `UvError` values through `Printer` at the command
entrypoint. The default error-chain renderer accepts the `Printer`
directly and owns hint collection and stream selection; `-q` preserves
final errors and `-qq` suppresses them while exit codes remain 1 for
user errors and 2 for unexpected errors. Stacked on #20188.

Part of #17110.
Closes #19326.
zanieb added a commit that referenced this pull request Jul 7, 2026
Our trace log that emits a debug representation of errors is useless for
`anyhow::Error` which is more common following
#20188.

For `UvError::User`, we elide the trace log entirely, I do not expect us
to need to debug those error chains.

For `UvError::Unexpected`, we introduce a new
`uv_errors::debug_error_chain` formatter that walks each source and
renders its `Debug` representation. To retain parity with the previous
implementation, we also log the backtrace if available.

e.g.:

```diff
-TRACE Error trace: Failed to create virtual environment
-
-Caused by:
-    Not a directory (os error 20)
+TRACE Error chain:
+0: Creation(Io(Os { code: 20, kind: NotADirectory, message: "Not a directory" }))
+1: Io(Os { code: 20, kind: NotADirectory, message: "Not a directory" })
 error: Failed to create virtual environment
   Caused by: Not a directory (os error 20)
```
zanieb added a commit that referenced this pull request Sep 11, 2026
Route the remaining package-operation errors through `UvError` and the
standard error-chain renderer, then remove uv's direct `miette`
dependency and global hook. Diagnostics use the same source-chain
formatting and hint collection as other commands, with cause-specific
hints before general command advice. No-solution headings omit trailing
punctuation, retain their command context, and are not repeated inside
build-dependency errors. Final errors remain visible with `-q` and are
suppressed with `-qq`.

Classify operation failures by their underlying cause instead of by
which renderer handles them. Each error type owns its classification,
and type-erased build errors forward it. Expected package, resolution,
build, integrity, and lock-validation failures use code 1, while
recognized transport, cache, filesystem, and internal failures use code
2. This deliberately changes some previously inconsistent statuses
without attempting to normalize every standalone command or opaque
archive-error path. Command-line argument errors remain code 2.
Third-party dependencies may still use `miette` internally.

Prior work:

- #14546 removed `miette` from `uv venv`.
- #17535 added first-party line wrapping.
- #18090 established the `Hint` and `Hints` APIs.
- #20155 made hints explicit in error-chain rendering.
- #20156 preserved indentation in multiline causes.
- #20159 migrated `uv build` errors to standard rendering.
- #20160 migrated tool requirement errors to standard rendering.
- #20188 introduced the explicit `UvError` model.
- #20163 routed final errors through `Printer` for `-q` and `-qq`.
- #20217 enabled cause-chain rendering for user errors.
- #21563 added verification of index-provided metadata hashes.
- #21279 reused URL-provided hashes during resolution.
- #21584 renamed the hint-producing trait to `Hinted`.
- #21577 added explicit hint ordering.

Follow-up work:

- #21566 collects hints for batched `uv tool upgrade` failures and fixes
their quiet-mode output.
- #21568 routes Python upgrade request errors and version-file hints
through `UvError`.
- #21587 separates operation-specific diagnostic context from
exit-status classification.
- #21599 renders error and warning causes with compact tree connectors.
zanieb added a commit that referenced this pull request Sep 11, 2026
Python upgrade rejects patch and prerelease requests by printing
directly to ordinary stderr, so `-q` hides the error and its
`.python-version` guidance. Represent this as a typed user error and
collect the version-file hint through `Hinted`. The message remains
visible with `-q`, is suppressed with `-qq`, and keeps exit code 1.
Explicit command-line version requests do not receive the version-file
hint.

Prior work:

- #20188 introduced the explicit `UvError` model.
- #20163 defines the final-error behavior for `-q` and `-qq`.
- #17110 consolidates the remaining operation-error rendering.
zanieb added a commit that referenced this pull request Sep 11, 2026
Resolution headings are assembled inside `UvError::from_operation`,
mixing operation-specific formatting with exit-status selection. Store
no-solution and contextual-requirement headings as typed
`operations::Error` variants, and attach command context before
converting to `UvError`. Add the default no-solution heading only at the
final command-error boundary so errors nested under higher-level build
or tool messages do not gain redundant headings. The original sources
and hints remain available, and diagnostic output and exit-status policy
are unchanged.

Prior work:

- #20188 introduced the explicit `UvError` model.
- #17110 routes operation errors through the standard diagnostic path.
- #21566 uses that path for batched tool-upgrade failures.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal A refactor or improvement that is not user-facing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant