fix(metadata): fail loudly when the sidecar write cannot land

update_model_metadata ignored the save_metadata result, so a fetch on a
drive that went offline mid-run was counted as success: the cache got
the fresh CivitAI payload while the durable sidecar never landed, and
every later fetch skipped the model as already fetched.

The save result now raises MetadataPersistError. In the bulk fetch path
this fails the item (reported in the summary, cache untouched, model
stays eligible for the next run); relink surfaces an honest 500.

Also corrects the stale known-limitation note in the scoped-scan plan:
a startup-offline root has been listed and re-admitted since Wave 6.
This commit is contained in:
Will Miao
2026-10-08 07:55:47 +08:00
parent 95acd6308a
commit acefe1a348
4 changed files with 71 additions and 5 deletions
+11 -2
View File
@@ -14,7 +14,7 @@ from ..utils.model_utils import determine_base_model
from ..utils.models import autov3_from_civitai_files
from ..utils.sidecar_paths import get_metadata_path
from .connectivity_guard import OFFLINE_FRIENDLY_MESSAGE, is_expected_offline_error
from .errors import RateLimitError
from .errors import MetadataPersistError, RateLimitError
from .model_metadata_provider import _LOCAL_PROVIDER_LABELS
from .model_sources import get_source_platform, has_external_source
@@ -231,7 +231,16 @@ class MetadataSyncService:
metadata_path, local_metadata, civitai_metadata.get("images", [])
)
await self._metadata_manager.save_metadata(metadata_path, local_metadata)
saved = await self._metadata_manager.save_metadata(metadata_path, local_metadata)
if not saved:
# A swallowed write failure would update the cache while the
# durable sidecar never lands (e.g. the drive went offline), and
# the model would be skipped by every later fetch as "already
# fetched". Fail loudly instead so the caller reports the item
# and it stays eligible for the next run.
raise MetadataPersistError(
f"Failed to write metadata sidecar: {metadata_path}"
)
return local_metadata
async def fetch_and_update_model(