Symptoms
java.io.FileNotFoundException: ... part-00012-xxxx.snappy.parquet/[DELTA_FILE_NOT_FOUND_DETAILED]on reads.- Long-running streaming or batch readers fail after a VACUUM.
- Time travel to older versions fails.
1. Why files are missing
| Cause | Typical sign |
|---|---|
VACUUM ... RETAIN 0 HOURS (retention check disabled) | Readers using older snapshots fail; recent history in DESCRIBE HISTORY shows VACUUM |
| ADLS lifecycle rule deleting or archiving "old" files | Files referenced by the current version disappear |
| Someone deleted files directly in storage | Random current files missing |
| Two tables sharing one path | One table's VACUUM deletes the other's files |
DESCRIBE HISTORY main.silver.orders LIMIT 20; -- look for VACUUM START/END and their parameters
2. Recover the files (best option)
If soft delete or versioning is on the storage account, restore the deleted blobs:
az storage blob list --account-name stlake -c silver --prefix tables/orders/ --include d --auth-mode login \
--query "[?deleted].name" -o tsv > missing.txt
while read -r b; do az storage blob undelete --account-name stlake -c silver -n "$b" --auth-mode login; done < missing.txt
If files went to the Archive tier via lifecycle, rehydrate them (az storage blob set-tier --tier Hot --rehydrate-priority High) — this takes hours.
3. No recovery possible: repair the table
Current version references missing files — remove those entries from the log so the table is readable again (data in those files is lost):
FSCK REPAIR TABLE main.silver.orders DRY RUN;
FSCK REPAIR TABLE main.silver.orders;
Then reload the lost data from bronze/raw for the affected partitions (re-run the load for those dates).
Only old versions are broken (readers time-travelling or long-running streams): restart those readers on the current version. For a stream reading the table as a source, you may need ignoreMissingFiles or a new checkpoint, depending on where it was.
Caution
FSCK REPAIR TABLEmakes the table consistent by forgetting files. RunDRY RUNfirst and record the list — it's your list of data to reload.
4. Safe retention
ALTER TABLE main.silver.orders SET TBLPROPERTIES (
'delta.deletedFileRetentionDuration' = 'interval 7 days',
'delta.logRetentionDuration' = 'interval 30 days');
- Keep
spark.databricks.delta.retentionDurationCheck.enabled = true(default) — it blocksRETAINbelow the safe threshold. - Retention must exceed your longest-running query or stream interruption.
- Prefer predictive optimization for managed tables, which runs VACUUM with safe defaults.
5. Storage hygiene
- No lifecycle delete/archive rules on paths holding Delta tables (lifecycle rules don't understand the transaction log).
- Enable blob soft delete on lake accounts.
- One table per path; Unity Catalog prevents overlapping locations for new tables.
Prevent it next time
- Never disable the retention check in production code.
- Review lifecycle policies on lake containers with the data team.
- Alert on
VACUUMwith low retention via audit logs/table history.