FTP delete not atomic / verified / transactional (?)

Yes, detailed by The REPAIR command

Tries to repair the backup. If no local database is found or the database is empty, the database is re-created with data from the storage. If the database is in place but the remote storage is corrupt, the remote storage gets repaired with local data (if available).

so it has two distinct functions. If you say you ran repair, should I take that as the no-database function? Maybe it’d be best not to even mention repair unless you’re doing that try-to-align-things case as well…

I think you hinted somewhere recently, but to ask again – are you finding these in disaster recovery test?
checker12.zip (1.3 KB)
What my script (which I’ll just just post even though you had to change for your environment) is looking for is blocks in aggregate, and not much in specific other things that could be going wrong, yet it’s still disappointing it saw nothing missing. I was manually making missing blocks yesterday, and did find one case it found that list-broken-files did not, and that was a metadata block of a folder. Testing a file, both methods found a missing block in a file’s data or metadata. This all followed expected recreate fail.
As expected, simply breaking the dindex didn’t make that, as it read the dblock instead. To break dblock is more complex because it changes the dblock size and hash, so those need to go back into dindex…

There’s more potential fault insertion testing, e.g. I didn’t try creating a fault in the list folder which is a convenience copy of a blocklist that’s also in the dblock, but one doesn’t want to read dblock in recreate.

So is test sequence running recreate to see if it can (a really good test, IMO), finds it can’t, then all tools (e.g. list-broken-files and my Python script) also can’t explain it? If so, that’s a pretty bad situation.

It sounds like you were trying pretty hard afterwards. The only good news is it seems a pretty solid fail…

Actual restores have more tricks in them, so I want to make sure I know what’s being run, and the order.
Are you doing a direct restore or a recreate, i.e. run a repair without a local database? That’s important.

The source code claims that the broken database is still allowable for restore, so is it a recreate then an ordinary restore from the somewhat broken database? That should be allowed (but might have issues), and it separates actions. Best DR restore test uses no-local-blocks to ensure it’s only using destination:

Duplicati will attempt to use data from source files to minimize the amount of downloaded data. Use this option to skip this optimization and only use remote data.

even if test system has no access to source (I don’t know), it would waste some time trying to get there.

Restore also has extensive logging that you can look at that possibly would shed light on a block failure.
We need as much data as possible, and preferably from logs because it’s designed and is more private.
Verbose level is as high as you need to go I think, and you can sanitize any filenames as seems proper.

So I guess that’s more than the default test, which is 1 set, typically 3 files. Perhaps this was using all?

The file can have a different hash algorithm than its blocks, but its hash is computed one block at a time.
A restore scatters blocks from dblock files as needed. If a source file block is missing, file hash notices it.