apply() deleted storage copies inside the BEGIN/COMMIT, so a failure partway through rolled the rows back and left the surviving rows pointing at files that were already gone. Collect the doomed paths during the transaction, COMMIT, then unlink — rows and files can now only be lost together. --apply also prints how many keys it removed (first 20), and main() closes the connection it opens.