dgtlmoon/changedetection.io · critical · Exception
Migration failed: {len(missing)} watch files missing: {missi
Error message
Migration failed: {len(missing)} watch files missing: {missing[:5]}... url-watches.json remains intact, safe to retry. What it means
A generic Exception raised in Phase 2 of migrate_legacy_db_format: after saving each watch, the migration verifies that <datastore>/<uuid>/watch.json exists for every uuid in url-watches.json. If any are missing it aborts, listing up to five offending uuids, with url-watches.json again left intact for a safe retry.
Source
Thrown at changedetectionio/store/updates.py:617
logger.error(f"Failed to save watch {uuid}: {e}")
raise Exception(
f"Migration failed: Could not save watch {uuid}. "
f"url-watches.json remains intact, safe to retry. Error: {e}"
)
logger.critical(f"Phase 1 complete: Saved {saved_count} watches")
# Phase 2: Verify all files exist
logger.critical("Phase 2/4: Verifying all watch.json files were created...")
missing = []
for uuid in self.data['watching'].keys():
watch_json = os.path.join(self.datastore_path, uuid, "watch.json")
if not os.path.isfile(watch_json):
missing.append(uuid)
if missing:
raise Exception(
f"Migration failed: {len(missing)} watch files missing: {missing[:5]}... "
f"url-watches.json remains intact, safe to retry."
)
logger.critical(f"Phase 2 complete: Verified {watch_count} watch files")
# Phase 3: Create new settings file
logger.critical("Phase 3/4: Creating changedetection.json...")
try:
self._save_settings()
except Exception as e:
logger.error(f"Failed to create changedetection.json: {e}")
raise Exception(
f"Migration failed: Could not create changedetection.json. "
f"url-watches.json remains intact, safe to retry. Error: {e}"
)
View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Check disk space and permissions, then simply restart the app — the migration is designed to be re-run
- Inspect the listed uuid directories: create/restore the missing watch.json or remove those uuids from url-watches.json if the watches are disposable
- Disable aggressive sync/AV on the datastore volume
- Back up the whole datastore dir (and url-watches.json) before retrying
Defensive patterns
Strategy: retry
Validate before calling
# pre-migration: verify the datastore dir is writable and has space import shutil assert shutil.disk_usage(datastore_path).free > len(watching) * 64 * 1024 # rough headroom
Try / catch
try:
update_26(datastore)
except Exception as e:
if 'watch files missing' in str(e):
time.sleep(30); restart_app() # migration is idempotent and safe to retry Prevention
- Avoid restarting/OOM-killing the container during a migration window
- Disable file sync/AV tooling on the datastore volume
- Keep the datastore on local disk rather than flaky network mounts during upgrades
When it happens
Trigger: Phase 1 reported success (or was interrupted) but one or more watch.json files are absent on disk — typically a process killed mid-migration, disk full causing silent write failures, or filesystem sync issues on network volumes.
Common situations: Container OOM-killed or restarted during a large migration; NFS/bind-mount caching hiding freshly written files; antivirus or sync tools (dropbox-style) deleting/moving new files; disk-full during Phase 1.
Related errors
- Migration failed: Could not save watch {uuid}. url-watches.j
- Migration failed: Could not create changedetection.json. url
- Disk full: Cannot save {label}
- Disk quota exceeded: Cannot save {label}
- I/O error saving {label}: {e}
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/f484034737beb88e.
Report an issue: GitHub.