graph TD
    Move["Move library<br/>to the new NAS"] --> Edit["Change the app's<br/>root folder"]
    Edit --> Scan["Rescan"]
    Scan --> Missing["Every stored path<br/>points at the old place"]
    Missing --> Zero["7,995 track records<br/>-> 0"]
    Zero --> Restore["Restore backup<br/>+ rewrite the paths"]

The new NAS finally had its storage, and a day of careful work moved 1.6 TB of media onto it. Every app that touches the library got the same treatment: write down a baseline first (how many series, how many files, how many gigabytes), change where the app looks, rescan, compare. Two of the three media managers passed instantly. Same counts, same sizes, done.

The third one didn’t.

Zero is a number

After changing its root folder, the music manager’s rescan ran for seven minutes and then failed. I checked the count: 7,995 track records had become 0. Every album now looked “missing”. The files themselves were fine on disk, and nothing had been deleted or downloaded, but the app’s idea of the library had been wiped.

The first move was the right one: stop the app immediately. An app that believes its whole library is missing is an app that wants to go and fetch it.

Why the other two were fine

The TV and movie managers store each file’s path relative to the show or movie folder. Move the folder, and the files follow. The music manager stores the full absolute path of every track. Changing the root folder only changed where new artists live. The 7,995 stored paths still said /music/..., a place that no longer existed inside the container, so the rescan concluded every file was gone and removed the records.

The fix, and a second mistake

With a full backup of the app’s configuration taken before the change, recovery was a few steps: restore the pre-change database, rewrite the paths in it while the app was stopped, start it without rescanning, and check two things: the counts matched the baseline exactly, and every one of the recorded files existed on the new storage. They did.

The second mistake was in my own script. It was meant to move the damaged database aside before restoring. That step failed on a permissions error, but the script kept going: a failing command inside an && chain doesn’t stop a shell running with set -e. The damaged copy was overwritten instead of preserved. It held nothing worth keeping, but “set aside, not deleted” was the plan, and the plan silently didn’t happen.

What I’m keeping

  • Take a baseline before every change, and a full backup of the app’s config. The baseline is what made “zero” obvious within a minute. The backup is what made it recoverable.
  • Find out how each app stores paths before moving anything. Relative and absolute look identical until the day you move the folder.
  • After a restore, verify against the disk, not just the counts. Counts can match while paths point nowhere.
  • A step that must not be skipped needs its own check. set -e does not protect a chain you wrote with &&.