Skip to content

v1.6.2

Choose a tag to compare

@jakemorgangit jakemorgangit released this 12 Aug 09:30
· 55 commits to main since this release
2a63e8e

Twelve fixes on top of 1.6.0/1.6.1. No breaking changes, no config or schema changes — upgrading is a straight swap of the exe.

Two of these were reported from the app while the release was being prepared; the rest came out of a systematic review of the screens and the engine.

The ones that could cost you something

Execute stayed live while a restore was running. The button took its enabled state from the same property that supplies the "why you cannot press this" sentence — and that sentence is deliberately empty during a run, because mid-restore the control anybody wants is Stop. Empty read as "not blocked". Two presses armed the button and called the run again, and the first thing that does is begin a new cancellation: the restore in flight abandoned mid-chain, its target left in RESTORING, and the whole thing started from the top. The Backup and Copy Database screens both had this right already; this was the one where WITH REPLACE has already dropped the target.

Connect announced a different server from the one it proved. A connection attempt is exactly the operation slow enough for somebody to click another entry in the list beside it. Every line after the await re-read that selection, so the app proved it could reach one server and then marked the other connected — handing it out as the connected server, which is the object the restore screen executes against. It also wrote the proved server's version banner onto the other one's saved entry, where it persists and drives the version preflights.

The exposure dashboard judged one clock against another. msdb records a backup's finish time in the instance's local time; the sweep compared it against the clock of the machine running the app. The log warning threshold is one hour, so any offset measured in hours decided the verdict outright. A server behind the app raised false alarms on healthy databases; a server ahead of it made backups look newer than they were — downgrading an alarm to a warning, and where the offset exceeded the real age, going negative and showing green. Each server is now asked for its own clock in the same query.

An S3 listing could loop forever. The paging loops stopped when the continuation token was null, but an XML element that is present and empty reads as "", not null. A provider that writes <NextContinuationToken/> on the last page instead of omitting it sent the loop back for another page with an empty token — which S3 reads as start from the beginning — re-listing the whole bucket until the process ran out of memory. AWS omits the element, so this never fired against S3 proper; it is the S3-compatible providers this feature exists for where that detail differs.

Recovery actions could be started on top of each other — on the panel you are looking at after a restore has failed, where pressing the second button abandoned the RESTORE ... WITH RECOVERY you were waiting on.

Screens that said the wrong thing

  • The Restore screen claimed there were no restore points before anything had been loaded — a red banner about a missing full backup, when the truth was that nobody had pressed Load Backups yet. It said it twice, too.
  • Choosing a target never connected to it. Step 2 offers "otherwise pick a saved server here" as the alternative to connecting on the SQL Servers screen, and set everything except the flag that gates Execute — so every step ticked green and the button told you to go to another tab and do what you had just done. It now attempts the connection and says what happened, including the reason if it failed. A failure never blocks generation: producing a script for an instance this machine cannot reach is exactly what Save to File, Copy as Agent job and Export runbook are for.
  • Four screens showed errors but never confirmations. A config import — a bulk operation over your server and container lists — reported what it had added and updated to nobody. An export's "the file holds no secrets" was never shown, which is the one thing worth knowing before emailing it to a colleague.
  • A fresh install told you to select things that did not exist, including Browse Backups asking for a container when none were configured.
  • Every container had a green dot whether or not it had a credential. That bites hardest right after a config import, since export carries no secrets by design — so a whole list came up green and could reach nothing.
  • Verify Last Backup had no busy state, and a second press cancelled and restarted it.
  • Ticking WITH MOVE cancelled a running chain verification.

Also

The saved execution log was going out unredacted; free space is reported on every restore rather than only after an optional button; the script verb can relocate; the CLI's exit-code contract is now checked against the code that implements it.

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.