Print a failed command's error once on stderr (closes #433) #451

Merged
clawbot merged 1 commits from issue-433-print-error-once into next 2026-11-11 07:38:11 +01:00
Collaborator

A command that failed after startup printed its error twice on stderr: once as an ERROR log record and once as the final ERROR: line the README documents. Closes #433.

The failure handlers in internal/cli (snapshot create, snapshot verify, snapshot restore, prune, info, remote info, and the commands that go through runVaultikApp) now log the failure at info level. The ERROR: line is unchanged and always printed, --quiet and --cron included. The log record appears only under --verbose or --debug.

Two failures also wrote their own ERROR record before reaching a handler:

  • A failed blob upload in snapshot create is now logged at info level.
  • A restore that stops on a file it cannot restore no longer logs that file's error. Under --skip-errors the restore goes on, and the error is still logged.

Judgement call: under --verbose the record's level reads INFO, not ERROR. Keeping ERROR would need the handlers to read the verbosity flags themselves. Reversing it is a one-line change per handler.

entry_failure_once_test.go requires one ERROR: line, and a record repeating it only under --verbose, for:

  • snapshot create, snapshot remove, snapshot verify, remote info and prune against a destination they cannot use;
  • a backup whose blob upload fails;
  • a restore whose blob download fails.

It fails on current next. info is not run: it cannot fail after startup.

The three snapshot create --prune tests in entry_snapshot_create_prune_test.go also require one ERROR: line and no record repeating it.

upload_cancel_log_test.go, from #434, now reads the log at --verbose level, and TestFailedUploadIsLoggedAsError is renamed TestFailedUploadIsLogged.

Model: opus-5-5

A command that failed after startup printed its error twice on stderr: once as an `ERROR` log record and once as the final `ERROR:` line the README documents. Closes https://git.eeqj.de/sneak/vaultik/issues/433. The failure handlers in `internal/cli` (`snapshot create`, `snapshot verify`, `snapshot restore`, `prune`, `info`, `remote info`, and the commands that go through `runVaultikApp`) now log the failure at info level. The `ERROR:` line is unchanged and always printed, `--quiet` and `--cron` included. The log record appears only under `--verbose` or `--debug`. Two failures also wrote their own `ERROR` record before reaching a handler: - A failed blob upload in `snapshot create` is now logged at info level. - A restore that stops on a file it cannot restore no longer logs that file's error. Under `--skip-errors` the restore goes on, and the error is still logged. Judgement call: under `--verbose` the record's level reads `INFO`, not `ERROR`. Keeping `ERROR` would need the handlers to read the verbosity flags themselves. Reversing it is a one-line change per handler. `entry_failure_once_test.go` requires one `ERROR:` line, and a record repeating it only under `--verbose`, for: - `snapshot create`, `snapshot remove`, `snapshot verify`, `remote info` and `prune` against a destination they cannot use; - a backup whose blob upload fails; - a restore whose blob download fails. It fails on current `next`. `info` is not run: it cannot fail after startup. The three `snapshot create --prune` tests in `entry_snapshot_create_prune_test.go` also require one `ERROR:` line and no record repeating it. `upload_cancel_log_test.go`, from https://git.eeqj.de/sneak/vaultik/issues/434, now reads the log at `--verbose` level, and `TestFailedUploadIsLoggedAsError` is renamed `TestFailedUploadIsLogged`. Model: opus-5-5
clawbot self-assigned this 2026-11-11 04:09:57 +01:00
clawbot added the needs-review label 2026-11-11 04:10:02 +01:00
Author
Collaborator

FAIL (needs-rework)

  1. Two failures still print their error twice on stderr without --verbose. The issue, #433, covers any command that fails after startup.

    • internal/vaultik/restore.go, handleRestoreFileError (log.Error("Failed to restore file", ...)): a restore that cannot download or decrypt a blob writes an ERROR record, then ends with ERROR: Restore failed: restoring ... carrying the same error.
    • internal/snapshot/scanner.go, uploadBlobIfNeeded (log.Error("Failed to upload blob", ...)): a backup whose blob upload fails writes an ERROR record, then ends with ERROR: Snapshot creation failed: ... carrying the same error.
    • Acceptable: when the error is returned and becomes the final line (for restore, without --skip-errors), the record is written at info level, as the command handlers now do, or not at all.
  2. internal/cli/entry_failure_once_test.go runs only snapshot create, remote info and prune. Putting log.Error back in runVaultikApp (app.go), info.go, snapshot_restore.go or the snapshot verify handler does not fail it. Acceptable: the test also runs a command through each changed handler (snapshot remove for runVaultikApp, info, snapshot verify, snapshot restore) and through both failures in finding 1.

Model: opus-5-5

FAIL (`needs-rework`) 1. Two failures still print their error twice on stderr without `--verbose`. The issue, https://git.eeqj.de/sneak/vaultik/issues/433, covers any command that fails after startup. - `internal/vaultik/restore.go`, `handleRestoreFileError` (`log.Error("Failed to restore file", ...)`): a restore that cannot download or decrypt a blob writes an `ERROR` record, then ends with `ERROR: Restore failed: restoring ...` carrying the same error. - `internal/snapshot/scanner.go`, `uploadBlobIfNeeded` (`log.Error("Failed to upload blob", ...)`): a backup whose blob upload fails writes an `ERROR` record, then ends with `ERROR: Snapshot creation failed: ...` carrying the same error. - Acceptable: when the error is returned and becomes the final line (for restore, without `--skip-errors`), the record is written at info level, as the command handlers now do, or not at all. 2. `internal/cli/entry_failure_once_test.go` runs only `snapshot create`, `remote info` and `prune`. Putting `log.Error` back in `runVaultikApp` (`app.go`), `info.go`, `snapshot_restore.go` or the `snapshot verify` handler does not fail it. Acceptable: the test also runs a command through each changed handler (`snapshot remove` for `runVaultikApp`, `info`, `snapshot verify`, `snapshot restore`) and through both failures in finding 1. Model: opus-5-5
Author
Collaborator

For the reworker: fix the two findings of #451 (comment) as their "Acceptable" lines say, and change nothing else. Rebase onto current origin/next, run make fmt and make check, push with --force-with-lease, and reply here with one line per finding.

For the next reviewer: check those two findings against the rework, and anything the rework broke.

Model: opus-5-5

For the reworker: fix the two findings of https://git.eeqj.de/sneak/vaultik/pulls/451#issuecomment-177437 as their "Acceptable" lines say, and change nothing else. Rebase onto current `origin/next`, run `make fmt` and `make check`, push with `--force-with-lease`, and reply here with one line per finding. For the next reviewer: check those two findings against the rework, and anything the rework broke. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-11-11 05:42:34 +01:00
clawbot force-pushed issue-433-print-error-once from 7a5942f8ed to 7fe467b3ba 2026-11-11 05:59:32 +01:00 Compare
clawbot force-pushed issue-433-print-error-once from 7fe467b3ba to a23a8fffa3 2026-11-11 06:07:34 +01:00 Compare
Author
Collaborator
  1. Fixed: a restore failure that ends the command is returned without a log record, and a failed blob upload is logged at info level, so upload_cancel_log_test.go now reads the log at --verbose level.
  2. Fixed: the test also runs snapshot remove, snapshot verify, the failed upload, and the failed blob download, which goes through the snapshot restore handler. Not done for info: its handler cannot run, since ShowInfo never returns an error.

Model: opus-5-5

1. Fixed: a restore failure that ends the command is returned without a log record, and a failed blob upload is logged at info level, so `upload_cancel_log_test.go` now reads the log at `--verbose` level. 2. Fixed: the test also runs `snapshot remove`, `snapshot verify`, the failed upload, and the failed blob download, which goes through the `snapshot restore` handler. Not done for `info`: its handler cannot run, since `ShowInfo` never returns an error. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-11-11 06:22:22 +01:00
Author
Collaborator

FAIL (needs-rework)

  1. internal/cli/snapshot.go, snapshot create failure handler: the two "Backup completed, but" branches (log.Info("Post-backup prune failed", ...) and log.Info("Backup completed with an error", ...)) have no test. Putting log.Error back in both leaves the suite green, so the doubled error can come back for a failed post-backup prune and for a backup that skipped files or found an empty or unmounted source path.
    • The three tests in internal/cli/entry_snapshot_create_prune_test.go (TestEntrySnapshotCreateReportsPostBackupPruneFailure, TestEntrySnapshotCreatePruneExitsNonZeroWhenSourceIsEmpty, TestEntrySnapshotCreatePruneExitsNonZeroWhenMountPointIsMissing) already reach both branches, but check only that the ERROR: line is there.
    • Acceptable: each of those three tests also requires, through failureOutput, one ERROR: line and no log record repeating it.

Model: opus-5-5

FAIL (`needs-rework`) 1. `internal/cli/snapshot.go`, `snapshot create` failure handler: the two "Backup completed, but" branches (`log.Info("Post-backup prune failed", ...)` and `log.Info("Backup completed with an error", ...)`) have no test. Putting `log.Error` back in both leaves the suite green, so the doubled error can come back for a failed post-backup prune and for a backup that skipped files or found an empty or unmounted source path. - The three tests in `internal/cli/entry_snapshot_create_prune_test.go` (`TestEntrySnapshotCreateReportsPostBackupPruneFailure`, `TestEntrySnapshotCreatePruneExitsNonZeroWhenSourceIsEmpty`, `TestEntrySnapshotCreatePruneExitsNonZeroWhenMountPointIsMissing`) already reach both branches, but check only that the `ERROR:` line is there. - Acceptable: each of those three tests also requires, through `failureOutput`, one `ERROR:` line and no log record repeating it. Model: opus-5-5
Author
Collaborator

For the reworker: fix the finding of #451 (comment) as its "Acceptable" line says, and change nothing else. Rebase onto current origin/next, run make fmt and make check, push with --force-with-lease, and reply here with one line.

For the next reviewer: check that finding against the rework, and anything the rework broke.

Model: opus-5-5

For the reworker: fix the finding of https://git.eeqj.de/sneak/vaultik/pulls/451#issuecomment-177735 as its "Acceptable" line says, and change nothing else. Rebase onto current `origin/next`, run `make fmt` and `make check`, push with `--force-with-lease`, and reply here with one line. For the next reviewer: check that finding against the rework, and anything the rework broke. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-11-11 06:48:59 +01:00
clawbot added 1 commit 2026-11-11 06:55:27 +01:00
A command that failed after startup wrote the error twice on stderr:
as an ERROR log record and as the final ERROR: line. The failure
handlers now log the failure at info level, so the record appears only
under --verbose or --debug, next to the records that led up to it.

A failed blob upload is logged at info level for the same reason. A
restore that stops on a file it cannot restore no longer logs that
file's error, which the final line carries; under --skip-errors it is
still logged.

Model: opus-5-5
clawbot force-pushed issue-433-print-error-once from a23a8fffa3 to 3e7c12aabf 2026-11-11 06:55:27 +01:00 Compare
Author
Collaborator
  1. Fixed: the three tests in internal/cli/entry_snapshot_create_prune_test.go now call failureOutput and require no log record repeating the ERROR: line.

Model: opus-5-5

1. Fixed: the three tests in `internal/cli/entry_snapshot_create_prune_test.go` now call `failureOutput` and require no log record repeating the `ERROR:` line. Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-11-11 07:11:44 +01:00
Author
Collaborator

PASS: a failed command now prints its error once on stderr, as the final ERROR: line, and the log record repeating it appears only under --verbose or --debug, as #433 asks.

Model: opus-5-5

PASS: a failed command now prints its error once on stderr, as the final `ERROR:` line, and the log record repeating it appears only under `--verbose` or `--debug`, as https://git.eeqj.de/sneak/vaultik/issues/433 asks. Model: opus-5-5
clawbot merged commit 6a8bb2f389 into next 2026-11-11 07:38:11 +01:00
clawbot deleted branch issue-433-print-error-once 2026-11-11 07:38:12 +01:00
Sign in to join this conversation.