From 14f0c48fdd47c9de1d53db881f16b2d275ca7cb2 Mon Sep 17 00:00:00 2001 From: Will Miao Date: Thu, 28 May 2026 17:19:27 +0800 Subject: [PATCH] fix(recipe): detect and repair corrupted checkpoints in repair flow Add corruption detection to _repair_single_recipe: if checkpoint.modelVersionId matches any LoRA's modelVersionId, the checkpoint is corrupted (a LoRA was saved as checkpoint). Clear the checkpoint and remove the matching LoRA entry, then let enrichment re-resolve the correct checkpoint from CivitAI metadata. This fixes the retroactive repair path for the modelVersionIds[0] fallback bug. --- py/services/recipe_scanner.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/py/services/recipe_scanner.py b/py/services/recipe_scanner.py index ca49f7db..8bb4b102 100644 --- a/py/services/recipe_scanner.py +++ b/py/services/recipe_scanner.py @@ -65,7 +65,7 @@ class RecipeScanner: cls._instance._civitai_client = None # Will be lazily initialized return cls._instance - REPAIR_VERSION = 3 + REPAIR_VERSION = 4 def __init__( self, @@ -292,6 +292,32 @@ class RecipeScanner: if recipe.get("repair_version", 0) >= self.REPAIR_VERSION: return False + # 1.5 Detect and clear corrupted checkpoint (LoRA data saved as checkpoint). + # A checkpoint whose modelVersionId also appears in a LoRA entry is + # definitely wrong — the CivitAI import code used to pick + # modelVersionIds[0] as the checkpoint, which was often a LoRA. + # Clearing it lets the enrichment flow re-resolve the correct + # checkpoint from CivitAI image metadata. + cp = recipe.get("checkpoint") + lora_mvids = { + l.get("modelVersionId") + for l in recipe.get("loras", []) + if l.get("modelVersionId") + } + if cp and cp.get("modelVersionId") and cp["modelVersionId"] in lora_mvids: + cp_mvid = cp["modelVersionId"] + logger.info( + "Recipe %s: checkpoint modelVersionId %s matches a LoRA — " + "clearing corrupted checkpoint and removing matching LoRA entry", + recipe.get("id"), + cp_mvid, + ) + recipe["checkpoint"] = None + recipe["loras"] = [ + l for l in recipe.get("loras", []) + if l.get("modelVersionId") != cp_mvid + ] + # 2. Identification: Is repair needed? has_checkpoint = ( "checkpoint" in recipe