Skip to content

Halt and ask instead of aborting when a package step fails - #4870

Open
sernik77 wants to merge 2 commits into
archlinux:masterfrom
sernik77:pacstrap-error-recovery
Open

sernik77 wants to merge 2 commits into
archlinux:masterfrom
sernik77:pacstrap-error-recovery

Conversation

@sernik77

@sernik77 sernik77 commented Nov 5, 2026 •

Copy link
Copy Markdown

Right now one broken package during pacstrap kills the whole install. You've
partitioned, picked everything, waited for the downloads, and then a single
conflict sends you back 5 minutes. This PR makes archinstall let you choose.

  • pacman output is classified (conflict, missing target, file conflict,
    unsatisfiable dep) and you get fixes that fit: keep one side, drop, rename,
    overwrite, retry. Plus always: drop to a shell and resume, or exit and
    save your config
    .
  • Unanswered prompts fall back to a safe default after 60s. If there isn't
    one, unattended runs abort instead of guessing.
  • No retry loops: it only retries if the package list actually changed.
  • Parses err.worker_log, not str(err). The latter is cut to 500 chars and
    often loses the line naming the conflict.
  • Choosing "Exit" doesn't print the "please file a bug" banner anymore.
  • Anything skipped gets listed again at the end.

Code: lib/error_recovery.py (generic prompt), lib/pacman/errors.py (pure
parser, tested on recorded pacman output), wired into Pacman.strap().

In action

jack2 + pipewire-jack in Additional packages. The conflicting package was
pulled in as a dependency, so dropping it wouldn't help, and only shell/exit
are offered:
image

After a failed manual fix in the shell, the same failure shows up again, so
it now offers to skip the remaining packages and carry on:
image

Why: I kept hitting the jack2 / pipewire-jack conflict myself, and losing
a whole install over one package felt wrong. So I spent a few hours of spare
time, doing my part in making Arch a slightly better place :)

AI disclosure: the idea and design are mine; Claude Opus 5.5 wrote the code,
the tests and the first draft of this text. I've reviewed and tested it and
can explain any part of it.

sernik77 and others added 2 commits November 4, 2026 22:07
A failed pacstrap run currently ends the installation. Replace that with a
prompt that describes the failure and offers a way out, so a single bad
package does not cost the user the whole install.

The prompt lives in lib/error_recovery.py and knows nothing about pacman:
callers pass the choices that make sense for their own failure, and the two
that always apply -- resolve it by hand in a shell, or exit -- are appended
automatically. Leaving the shell asks whether to resume; exiting offers to
save the configuration first, which main.py honours. Unanswered prompts fall
back to a caller-declared safe choice after 60 seconds.

Where no choice is safe without a human, `safe=None` makes the prompt wait
rather than guess, and an unattended run aborts instead of picking
something. Conflicts usually arise between transitive dependencies rather
than requested packages, so dropping one from the request list would be a
no-op and the retry would fail identically. Two guards prevent that loop: a
retry only happens when the package list actually changed, and the same
failure signature twice in a row stops offering the same way out.

lib/pacman/errors.py classifies pacman output into conflicts, missing
targets, file conflicts and unsatisfiable dependencies. It does no I/O, so
it is tested against recorded pacman output. It reads err.worker_log rather
than str(err), which is truncated to the last 500 characters and routinely
cuts off the line naming the conflict.

Choosing "Exit" is a decision, not a fault, so Installer.__exit__ skips the
bug report banner for InstallationAbortedError and lets main() report it.

Anything skipped during recovery is re-listed once the installation
finishes, so an auto-continued prompt cannot silently produce an
incomplete system.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check-docstring-first treats string literals after module constants as extra
module docstrings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sernik77
sernik77 requested a review from Torxed as a code owner November 5, 2026 00:27

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.

1 participant