fix(upscale): deferred upscales (run_upscales_at_end) no longer skip every image with 'no filename in manifest'

Generated manifest items carry only a /view URL in 'file'; the deferred phase read 'filename', which only
upscaled and scanned items have, so every deferred job was skipped. New pure helper manifest_utils.item_filename
(filename key, else the URL's filename= parameter) is used there; the dashboard upscale path already parsed the URL.
Found by the wave-2 live base-dims check on the 3070.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Jason Hoku
2026-11-04 01:29:46 -08:00
co-authored by Claude Fable 5.1
parent 197b3f1a5d
commit 6b601632f6
4 changed files with 64 additions and 2 deletions
+3 -2
View File
@@ -17,7 +17,7 @@ from comfy.model_management import InterruptProcessingException
from .trigger_words import collect_unique_prompts_with_triggers, build_prompt_with_triggers, clear_trigger_caches
from .batch_encoding import batch_encode_prompts, encode_prompt_with_combinators, pinned_clip, DEFAULT_TE_BATCH_SIZE
from .manifest_utils import load_existing_manifest, save_manifest
from .manifest_utils import load_existing_manifest, save_manifest, item_filename
from .model_loader import (
load_checkpoint, load_loras, cleanup_model_references,
get_latent_channels, get_latent_downscale_ratio, make_empty_latent, load_loras_for_preencoding,
@@ -442,7 +442,8 @@ def run_deferred_upscales(
print(f"[GridTester] ⚠️ Deferred upscale #{job_idx+1}: base image not found in manifest, skipping")
continue
base_filename = base_item.get("filename")
# generated items carry only a /view URL ("file"); upscaled/scanned ones also have "filename"
base_filename = item_filename(base_item)
if not base_filename:
print(f"[GridTester] ⚠️ Deferred upscale #{job_idx+1}: no filename in manifest, skipping")
continue
+17
View File
@@ -336,6 +336,23 @@ def append_items(manifest_path, items, remove_ids=(), session_name=None, default
return data
def item_filename(item):
"""The image file name of a manifest item: its "filename" key when present, else the ``filename=`` query
parameter of its ``file`` (/view?...) URL, URL-decoded. Generated items only carry ``file``; upscaled and
scanned items also carry ``filename``. Returns "" when neither is usable."""
if not isinstance(item, dict):
return ""
name = item.get("filename")
if name:
return str(name)
url = item.get("file") or ""
m = re.search(r"[?&]filename=([^&]+)", str(url))
if not m:
return ""
from urllib.parse import unquote
return unquote(m.group(1))
def base_dims_of(item):
"""{"base_width","base_height"} of the generated image an upscale of `item` starts from ({} if unknown)."""
bw, bh = item.get("base_width"), item.get("base_height")
+1
View File
@@ -109,6 +109,7 @@ _GEN_ORCH_DEPS = {
"save_manifest": lambda *a, **kw: None,
"preserve_disk_comparisons": lambda *a, **kw: None,
"base_dims_of": lambda item: {},
"item_filename": lambda item: (item or {}).get("filename", ""),
"update_manifest_comparisons": lambda *a, **kw: {"comparisons": [], "added": 0, "removed": 0, "total": 0},
},
"model_loader": {
+43
View File
@@ -0,0 +1,43 @@
"""manifest_utils.item_filename: generated items carry only a /view URL, upscaled/scanned ones a filename.
The deferred-upscale phase (run_upscales_at_end) skipped every image with "no filename in manifest" before it
used this helper; the source-scan test pins that call."""
import importlib.util
import os
import re
_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def _load(name, modname):
spec = importlib.util.spec_from_file_location(modname, os.path.join(_ROOT, name))
m = importlib.util.module_from_spec(spec)
m.__package__ = os.path.basename(_ROOT)
spec.loader.exec_module(m)
return m
mu = _load("manifest_utils.py", "mu_item_filename")
def test_filename_key_wins():
assert mu.item_filename({"filename": "img_1.webp", "file": "/view?filename=other.webp"}) == "img_1.webp"
def test_parsed_from_view_url():
url = "/view?filename=img_179378440462348.webp&type=output&subfolder=benchmarks/S/images"
assert mu.item_filename({"file": url}) == "img_179378440462348.webp"
assert mu.item_filename({"file": "/view?type=output&filename=a%20b.png&subfolder=x"}) == "a b.png"
def test_unusable_items():
assert mu.item_filename({}) == ""
assert mu.item_filename({"file": "/view?type=output"}) == ""
assert mu.item_filename(None) == ""
def test_deferred_upscales_use_the_helper():
src = open(os.path.join(_ROOT, "generation_orchestrator.py"), encoding="utf-8").read()
start = src.index("def run_deferred_upscales(")
body = src[start:start + 6000]
assert "item_filename(base_item)" in body
assert not re.search(r'base_item\.get\("filename"\)', body)