Transactions and recovery
After an interrupted or failed package operation, inspect its history,
recover pending work, and verify what is on disk before making another change.
Use undo or downgrade only when you mean to reverse a committed change.
| What you see | What to do |
|---|---|
| A pending transaction after an interruption | Run peipkg recover, then inspect history and verify files |
| A committed update you want to reverse | Review undo or downgrade |
A rolled-back record but damaged or missing files | Follow failed-rollback checks; history alone is not proof of restoration |
| A committed change with a maintenance warning | Read the warning; a failed post-commit side effect does not undo the package change |
| An interrupted feature script | Use feat recovery; package recovery does not reverse feature setup |
Recovering an interrupted transaction #
Use the same root as the failed operation. If it was an offline or named
root, put --root TARGET before each command below.
peipkg history
peipkg recover
peipkg history
peipkg verify
- Record the transaction id, state, affected packages and error. Do not delete staged files or backups before recovery has had a chance to use them.
- Run
recover. A pending single-root transaction is rolled back; if none is pending, the command says so. A committed transaction has only cleanup left and is not reversed byrecover. - Read the result and inspect history again. Recovery can itself fail.
- Verify the affected packages, or all packages as above. Review each
difference against intentional edits and any
.peipkg-newfile.
Ordinary install, upgrade and removal commands attempt recovery of pending
single-root work before starting new work. Explicit recover lets you deal
with the interruption first and produces a recovery audit event; the automatic
path does not. Read-only package queries remain available without waiting
for the transaction lock. A second writer reports transaction in progress;
wait for that operation to finish before trying another change.
Across more than one root #
A multi-root upgrade has one combined plan and coordinated execution; it is not a series of independent per-root upgrades. See Named roots for the preparation and sequential-commit boundaries. Preparation rollback can fail; in the reviewed source that path retains a pending journal. Do not treat it as the older closed-journal failure described elsewhere on this page.
For recovery:
- Retain the original named-root topology and make every participating
root present and reachable. Run
peipkg recoverexplicitly from the same system anchor, using the original--root TARGETif one was selected. An ordinary single-root operation refuses pending cross-root work in isolation. Recovery discovers reachable roots; it does not prove that a missing or unregistered participant has been found. - Read the outcome. If no participant committed, pending participants are rolled back. If a participant committed, pending participants are rolled forward using persisted completion data. Missing or malformed data causes refusal; a later recovery step can fail after another root was reconciled.
- Inspect history and verify files in every participant. In this source,
the CLI's rolled back cross-root transaction line is printed after
either backward or forward reconciliation. It is not proof of rollback;
the forward path records
rolled forward: cross-root recoveryin the transaction. Keep the diagnostics and treat any refused or unreachable root as unresolved. - Review maintenance separately. Roll-forward recovery applies persisted
package metadata and attempts backup cleanup, but does not invoke the
normal post-commit side-effect runner. Do not assume it re-ran
depmodorman-db. Use the invocation reference to identify the affected root and kernel release, and verify the needed maintenance before relying on that system.
This follows peipkg 8b588ae8's
CLI root discovery and report,
coordinated recovery decision,
and roll-forward implementation.
It is a source-level contract, not evidence that recovery or maintenance
succeeded on a particular machine. Check the revision supplied by the image.
The technical recovery chapter
keeps the implementation context.
When recovery does not restore the files #
The failure reference
retains an earlier description of a closed-journal failure after I/O
errors, a filesystem becoming read-only, or permissions changing. If that
is the state you actually find, another recover can find nothing to retry.
Do not assume all failed rollbacks have that outcome: the reviewed
cross-root preparation rollback reports errors
and retains the affected pending journal. Inspect the transaction and tool
version before choosing the recovery path.
- Use
peipkg verifyto identify recorded files that differ or are missing. - Inspect the affected paths for staged or backup siblings, and keep the evidence while deciding whether the old or new content is wanted.
- Establish why writes or restoration failed before attempting repair.
- Reconcile affected files and package records manually where necessary.
There is no
reinstallverb: the reference describes removal and installation as two transactions, or a version change and change back. Review dependency, feature and claim consequences before removing anything. - Verify again after repair. A clean file check does not test services, feature scripts, registry state or user data.
The indeterminate-state reference
describes proposed handling beyond the available history, recovery and file
verification tools; it does not establish a forensic-report command or a
recover option to accept the current filesystem as authoritative. Its older
blanket recovery wording must not override the coordinated cross-root path
above. A closed journal and a pending cross-root journal require different
responses.
The transaction log #
peipkg history
history prints the transactions peipkg has carried out, most recent first — each with an id, a timestamp, its state (committed, rolled-back, or pending), and a short summary.
$ peipkg history
49 2026-05-19T14:02:10Z committed upgrade nginx, zlib
48 2026-05-19T09:31:55Z committed install nginx
47 2026-05-18T22:14:03Z rolled-back install brokenpkg
| Option | Effect |
|---|---|
-n N | Show at most N transactions. -n 0 shows all of them. The default is 20. |
--json | Emit JSON: for each transaction its id, state, started_at, summary, and operations, each an action (install, upgrade, downgrade, remove or claim), the package name, and its from and to versions where they apply. |
The history is what undo reads to find the most recent transaction, and what ties a stray *.peipkg-backup-<id> file back to the operation that created it.
What an interruption leaves behind #
| Name | Meaning |
|---|---|
<name>.peipkg-staged-<id> | Incoming content staged beside its destination |
<name>.peipkg-backup-<id> | The displaced original, renamed beside its destination |
The names have no leading dot and carry the transaction id shown by
history. They are recovery material, not ordinary cache files. Do not
remove them just to tidy a directory after an interruption. A committed
transaction can also leave cleanup behind after a crash; use its recorded
state and the recovery reference
to distinguish the cases.
Configuration files on upgrade #
Package defaults live under /usr/etc/; /etc/ is the merged configuration
view. Modified-file protection also recognises legacy package paths under
/etc/. It does not make /etc/ a current package destination.
When a default is unchanged since installation, an upgrade can replace it.
When you edited it, peipkg preserves your file and writes the new default as
<name>.peipkg-new, with a warning. Compare and merge the changes deliberately.
The new sibling is unowned and is not removed by uninstall. The original
path can continue to appear in verify because its recorded hash is now the
new package's hash; that report alone does not mean your preserved edit is
corruption. See Configuration files.
Side effects run after commit #
A package can request a standard maintenance operation from a closed set; it cannot supply arbitrary install-time scripts. Those maintenance steps run after commit. A failure is reported as a warning, and the package change stands. Read which step and root failed, then use the invocation and retry rules for that step. A later transaction that requests it can run it again; a warning does not mean the cache was already repaired.
The three phases #
For operating the system, distinguish the plan you can decline, the work in progress, and the reported outcome. A dry run previews a request without applying package changes; it does not reserve the metadata or installed state for a later invocation. The commit procedure and journal describe the implementation.
The one instant that matters #
For a single-root transaction, the database commit is the durability boundary:
pending work is recovered by rollback, while committed work is not reversed
by recover. This boundary does not remove the failure and visibility limits
above. See Atomicity and
Crash recovery.
Backups make rollback free #
Renaming displaced files avoids copying their contents for rollback; it does not make restoration infallible or promise a lasting backup. The backup reference says ordinary transaction backups are discarded at commit, while earlier operator guidance described a retention window. Do not rely on transaction backups for a later undo. The undo reference describes resolving from archive metadata and requiring a reachable repository or usable cache. Keep independent backups for data you must recover.
Why this shape #
Planning, journalling and a database commit support recovery; they are not a whole-system snapshot. Package-version reversal affects the package payload, not registry state, runtime data, user data or feature setup. The transaction and rollback chapters hold the implementation detail and its limits.