FTP delete not atomic / verified / transactional (?)

Is this database or files? If you have a preserved damaged database, that could be helpful.
We can either log Duplicati’s failed recreate better, or let my Python script look for troubles.

This is what I want to be able to forecast. If current tools can’t predict it, it needs better tools.
What to do to solve it is a different issue, but the surprise failures are bad to find at DR time.

People should of course be testing DR and DB recreate sometimes, but very few will do that.
Additionally, things could break between tests, so it’d be nice to understand this corruption…

My general assumption from long recreates and ones that run long and still come up empty is
something is missing. There are others here who know the exact SQL check better, but I took
kind of a brute-force check of reverse-engineering the file formats to check for missing blocks.

Database and destination internals has some output. I’ve decided duplicates are likely normal.

Here’s its ending, where it tries to find missing information of different sorts. Can you use this?

print(len(dindex_block_set), "blocks seen in dindex files")
print(len(dindex_blocklist_set), "blocklists seen in dindex files")
if missing := dindex_blocklist_set - dindex_block_set:
    print("Missing", missing)
print(len(dlist_blocklist_set), "blocks used by dlist files blocklists")
if missing := dlist_blocklist_set - dindex_blocklist_set:
    print("Missing", missing)
print(len(dindex_blocklist_block_set), "blocks used by dlist large files data")
if missing := dindex_blocklist_block_set - dindex_block_set:
    print("Missing", missing)
print(len(dlist_block_set), "blocks used by dlist small files data")
if missing := dlist_block_set - dindex_block_set - {"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="}:
    print("Missing", missing)
print(len(dlist_meta_block_set), "blocks used by dlist files metadata")
if missing := dlist_meta_block_set - dindex_block_set:
    print("Missing", missing)
print(len(dindex_block_set - dlist_block_set - dlist_blocklist_set - dindex_blocklist_block_set - dlist_meta_block_set), "blocks unused")
print(len(dlist_blockset_set), "large blocksets in dlist files")
print(len(dlist_block_set), "small blocksets in dlist files")
print("small file blocksets that are also metadata blocksets:", dlist_block_set.intersection(dlist_meta_block_set))
print("small file blocksets that are also blocklists:", dlist_block_set.intersection(dindex_blocklist_set))