Back up now always fails: restic exclude flags placed before the backup subcommand #73

Closed
opened 2026-10-13 19:58:53 +08:00 by Breadway · 4 comments
Owner

How it was found: clicking through the 98be903 build in a headless BOS live VM on 2026-10-13. Backup & restore > A folder or drive > /home/liveuser/backup-target, password set, Back up now. The page said "The backup didn't finish", and Details showed: unknown command "node_modules" for "restic". Same result with an empty folder and with an already-initialised repo (0 snapshots written either way).

Confidence: high. The error text matches the argv that src/src/commands/backup.rs restic_backup builds (lines ~204-210): restic --repo R --exclude-caches --exclude node_modules --exclude target ... backup $HOME. --exclude / --exclude-caches are flags of the backup subcommand, not global flags, so restic stops at them and treats "node_modules" as the subcommand.

Bug: no home-folder backup can ever succeed, manual or scheduled. Because the error text never says "does not exist", Backup.svelte's first-run fallback (restic_init then retry) never runs either, so a new repo is never created. The scheduled path at line ~497 should be checked for the same ordering.

Fix: build --repo R backup <excludes...> $HOME (excludes after backup). Add a unit test that asserts the argv order (index of "backup" is before the first "--exclude"), and ideally an integration test that runs restic init+backup against a temp dir when restic is on PATH.

**How it was found:** clicking through the 98be903 build in a headless BOS live VM on 2026-10-13. Backup & restore > A folder or drive > /home/liveuser/backup-target, password set, Back up now. The page said "The backup didn't finish", and Details showed: `unknown command "node_modules" for "restic"`. Same result with an empty folder and with an already-initialised repo (0 snapshots written either way). **Confidence:** high. The error text matches the argv that src/src/commands/backup.rs `restic_backup` builds (lines ~204-210): `restic --repo R --exclude-caches --exclude node_modules --exclude target ... backup $HOME`. `--exclude` / `--exclude-caches` are flags of the `backup` subcommand, not global flags, so restic stops at them and treats "node_modules" as the subcommand. **Bug:** no home-folder backup can ever succeed, manual or scheduled. Because the error text never says "does not exist", Backup.svelte's first-run fallback (restic_init then retry) never runs either, so a new repo is never created. The scheduled path at line ~497 should be checked for the same ordering. **Fix:** build `--repo R backup <excludes...> $HOME` (excludes after `backup`). Add a unit test that asserts the argv order (index of "backup" is before the first "--exclude"), and ideally an integration test that runs restic init+backup against a temp dir when restic is on PATH.
Author
Owner

Confirmed: scheduled_backup() (backup.rs ~491-496) builds the same order (--repo, excludes, then backup), so daily/weekly scheduled backups fail too, silently (only a user journal line).

Confirmed: scheduled_backup() (backup.rs ~491-496) builds the same order (--repo, excludes, then backup), so daily/weekly scheduled backups fail too, silently (only a user journal line).
Author
Owner

PR: #75 (head 5acab56)

PR: https://git.breadway.dev/Breadway/bos-settings/pulls/75 (head 5acab56)
Author
Owner

Review of BSET-72 at exact head 5acab56f82 (base main 14d1315872)

Verdict: code accepted, merge BLOCKED pending CI. The required Forgejo check "check / check (push)" on 5acab56 has been "Waiting to run" (queued behind a bread-ecosystem job on the shared self-hosted runner) since 20:41 and was still pending at 21:08 after bounded polling.

Criteria:

  • Back up now uses --repo R backup <excludes...> $HOME: pass. restic_backup calls the new backup_args (src/src/commands/backup.rs:197-202, 215).
  • scheduled_backup uses the same order: pass. It also calls backup_args (backup.rs:552).
  • Unit test asserts argv order: pass. backup_subcommand_precedes_its_flags (backup.rs:494-504).
  • Integration test with real restic init+backup when restic is on PATH: pass. restic_accepts_backup_args (backup.rs:506-545) runs init, backup and ls latest. It asserts note.txt is included and .cache/skip.txt is excluded. Ran locally with restic 0.19.1.
  • No capability regressions: pass. exclude_args is unchanged, so the excludes are identical. HOME source and RESTIC_PASSWORD env are unchanged in both paths.
  • Init fallback: when the repo is missing, the new order gives "Fatal: repository does not exist ... Is there a repository", which matches the Backup.svelte:52 regex. The first-run init path can now run.

Evidence (detached scratch worktree at 5acab56):

  • Old argv reproduced with restic 0.19.1: unknown command "node_modules" for "restic".
  • frontend: npm ci, npm run check (0 errors / 0 warnings), npm test (3 pass), npm run build: OK.
  • src: cargo fmt --check OK. cargo clippy --locked --all-targets -D warnings OK. cargo test --locked: 146 passed, 0 failed.
  • PR: 1 file changed, no review comments or change requests, mergeable=true.

Next action: merge with a merge commit once "check / check (push)" is green on 5acab56 and the head/base are re-confirmed.

Review of BSET-72 at exact head 5acab56f82da9b42d3e2cf374719c6662ca9b33c (base main 14d13158722527ff88f810b5c32f6679cea34833) Verdict: code accepted, merge BLOCKED pending CI. The required Forgejo check "check / check (push)" on 5acab56 has been "Waiting to run" (queued behind a bread-ecosystem job on the shared self-hosted runner) since 20:41 and was still pending at 21:08 after bounded polling. Criteria: - Back up now uses `--repo R backup <excludes...> $HOME`: pass. restic_backup calls the new backup_args (src/src/commands/backup.rs:197-202, 215). - scheduled_backup uses the same order: pass. It also calls backup_args (backup.rs:552). - Unit test asserts argv order: pass. backup_subcommand_precedes_its_flags (backup.rs:494-504). - Integration test with real restic init+backup when restic is on PATH: pass. restic_accepts_backup_args (backup.rs:506-545) runs init, backup and ls latest. It asserts note.txt is included and .cache/skip.txt is excluded. Ran locally with restic 0.19.1. - No capability regressions: pass. exclude_args is unchanged, so the excludes are identical. HOME source and RESTIC_PASSWORD env are unchanged in both paths. - Init fallback: when the repo is missing, the new order gives "Fatal: repository does not exist ... Is there a repository", which matches the Backup.svelte:52 regex. The first-run init path can now run. Evidence (detached scratch worktree at 5acab56): - Old argv reproduced with restic 0.19.1: `unknown command "node_modules" for "restic"`. - frontend: npm ci, npm run check (0 errors / 0 warnings), npm test (3 pass), npm run build: OK. - src: cargo fmt --check OK. cargo clippy --locked --all-targets -D warnings OK. cargo test --locked: 146 passed, 0 failed. - PR: 1 file changed, no review comments or change requests, mergeable=true. Next action: merge with a merge commit once "check / check (push)" is green on 5acab56 and the head/base are re-confirmed.
Author
Owner

Verified on integrated main a7b3e8b (merge 3c91bfd, PR #75): restic_accepts_backup_args runs real restic init+backup+ls against a temp repo (note.txt kept, .cache excluded); backup_subcommand_precedes_its_flags; 179 cargo tests pass. Scheduled path shares backup_args.

Verified on integrated main a7b3e8b (merge 3c91bfd, PR #75): restic_accepts_backup_args runs real restic init+backup+ls against a temp repo (note.txt kept, .cache excluded); backup_subcommand_precedes_its_flags; 179 cargo tests pass. Scheduled path shares backup_args.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/bos-settings#73
No description provided.