v1.6.1
Fixes on top of 1.6.0, plus two small additions. No breaking changes, no config or schema changes — upgrading is a straight swap of the exe.
Four defects that generated wrong T-SQL
A backup set with no files generated a restore that ends the sequence. A set discovered with nothing recorded against it produced RESTORE DATABASE [x] WITH RECOVERY naming no device. That is not a syntax error — it is the valid recovery-only form, so nothing failed at run time. Against a target sitting in RESTORING (a log-shipping secondary, a paused restore) it brought the database online wherever it had reached and ended the restore sequence permanently: no further log could be applied and the whole chain had to start again. The validator now reports it, the restore screen explains it, and the generator refuses to emit it.
A striped set missing its first file passed validation. The stripe check returned early on a single-file set, so a set holding only ..._2.bak — stripe 1 purged by retention, or never uploaded — passed clean, while the same set as stripes 2 and 3 was correctly flagged. It was blind precisely at its worst case. The question is now asked of the stripe numbers rather than the file count.
One striped set written across two folders was offered as two restore points. Multi-directory striping arrived as two sets at the same instant, each holding half a media set and each looking complete. A chain that should have offered four restore points offered seven, every one of them restoring from half a set. The halves are now recognised by their stripe numbers; two genuinely complete backups sharing a timestamp are left alone as the warning they are.
KEEP_REPLICATION and the broker options rode on NORECOVERY statements. SQL Server refuses that combination outright — Msg 3031 — so the first statement failed and the option was unusable for any chain longer than one statement, which is every log-shipping and replication scenario it exists for. They now go only on the statement that recovers, which is deliberately not the same as the last statement.
A saved log that was going out unredacted
Save output on the execution console wrote the raw console text. The method that adds a header naming the server, the target and the outcome — and runs the result through the redactor, with a comment explaining that this file gets attached to tickets — existed, was documented, and was called from nowhere. SAS signatures in the console were going out in saved logs.
Screens that said nothing, or the wrong thing
- Browse Backups had no error banner and no status line, so an expired SAS, a 403, a DNS failure, a genuinely empty container and never having pressed the button all left the identical screen. Pressing Load Backups with nothing selected was a button that visibly did nothing.
- Connect on the SQL Servers screen wrote its failure to a banner that only renders while the edit form is open — the form its own button is hidden behind. On the last step of first run, a typo'd instance flashed "Connecting..." and returned to a screen with nothing on it, while Test, one button away, explained itself properly.
- The Backup and Copy consoles vanished when the run ended, taking SQL Server's own account of the failure with them. On the copy screen that console is where the literal
RESTORE ... WITH RECOVERYstatements needed to get the target out of RESTORING are printed — so the app hid them, and the only way back was to re-run a production operation. - A container that answered and held nothing reported "Connected! 0 files found (0 B)" in the voice of a tick. It is the commonest new-user failure there is, and the cost of dressing it as success is an inexplicably empty Browse Backups two screens later.
- Ctrl+0..9 stayed live behind the first-run mode cards, landing on a screen with the sidebar collapsed to zero width, no mode chosen and no way back — an app that had to be restarted.
- The saved-containers list turned white while the Add Container form was open, in every theme, because a disabled
ListBoxtakes a system colour while its rows keep drawing their text in white.
Added
scriptcan relocate.--target,--relocate,--data-pathand--log-path, so generate-here-hand-over-run-there stops silently dropping its WITH MOVE clauses. Relocation needs an instance to ask — the logical file names come from FILELISTONLY and the default directories from the instance — so those flags are refused without a--targetrather than quietly ignored.- The About screen links to the documentation, the issue tracker and the releases. Until now the only hyperlink anywhere in the app was blackcat.wales.
Also
Free space is reported on every restore rather than only after an optional button. SECURITY.md no longer claims Entra ID is unsupported, and lists all four credential-vault prefixes rather than two. The README front-loads all three storage media and finally documents the S3 key pair's permissions and the IDENTITY = 'S3 Access Key' credential. The four v1.0.0-era screenshots are reshot. And the CLI's exit-code contract is now checked against the code that implements it — the gap that let two exit-code bugs survive.
Full detail in CHANGELOG.md.
Downloads. NineLives.exe is the app, 9lives.exe the CLI; take the -arm64 builds on Windows on ARM. Both are single self-contained executables — no installation. The zips carry both front ends together.
The binaries are unsigned, so SmartScreen will warn on first run (#33); each release carries a build provenance attestation you can verify with gh attestation verify.