Fix cached outputs missing from job results when prompt has no client_id (#14939)
Some checks are pending
Detect Unreviewed Merge / detect (push) Waiting to run
Python Linting / Run Ruff (push) Waiting to run
Python Linting / Run Pylint (push) Waiting to run
Build package / Build Test (3.14) (push) Waiting to run
Build package / Build Test (3.10) (push) Waiting to run
Build package / Build Test (3.11) (push) Waiting to run
Build package / Build Test (3.12) (push) Waiting to run
Build package / Build Test (3.13) (push) Waiting to run
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Waiting to run
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Waiting to run
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Waiting to run
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Waiting to run
Execution Tests / test (windows-latest) (push) Waiting to run
Execution Tests / test (macos-latest) (push) Waiting to run
Execution Tests / test (ubuntu-latest) (push) Waiting to run
Test server launches without errors / test (push) Waiting to run
Unit Tests / test (macos-latest) (push) Waiting to run
Unit Tests / test (ubuntu-latest) (push) Waiting to run
Unit Tests / test (windows-2022) (push) Waiting to run

When a prompt is submitted without client_id and its output nodes are
served from cache, _send_cached_ui returned early before recording the
cached UI outputs, so /api/jobs/{job_id} (and /history) reported success
with empty outputs. Record the outputs before the client_id check.
This commit is contained in:
Alexander Piskun 2026-07-15 00:29:01 +03:00 committed by GitHub
parent 26537080cb
commit 1701cce8dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 26 additions and 2 deletions

View File

@ -426,12 +426,12 @@ def _is_intermediate_output(dynprompt, node_id):
def _send_cached_ui(server, node_id, display_node_id, cached, prompt_id, ui_outputs): def _send_cached_ui(server, node_id, display_node_id, cached, prompt_id, ui_outputs):
if cached.ui is not None:
ui_outputs[node_id] = cached.ui
if server.client_id is None: if server.client_id is None:
return return
cached_ui = cached.ui or {} cached_ui = cached.ui or {}
server.send_sync("executed", { "node": node_id, "display_node": display_node_id, "output": cached_ui.get("output", None), "prompt_id": prompt_id }, server.client_id) server.send_sync("executed", { "node": node_id, "display_node": display_node_id, "output": cached_ui.get("output", None), "prompt_id": prompt_id }, server.client_id)
if cached.ui is not None:
ui_outputs[node_id] = cached.ui
async def execute(server, dynprompt, caches, current_item, extra_data, executed, prompt_id, execution_list, pending_subgraph_results, pending_async_nodes, ui_outputs): async def execute(server, dynprompt, caches, current_item, extra_data, executed, prompt_id, execution_list, pending_subgraph_results, pending_async_nodes, ui_outputs):
unique_id = current_item unique_id = current_item

View File

@ -818,6 +818,30 @@ class TestExecution:
except urllib.error.HTTPError: except urllib.error.HTTPError:
pass # Expected behavior pass # Expected behavior
def test_cached_outputs_in_job_without_client_id(self, client: ComfyClient, builder: GraphBuilder):
g = builder
image = g.node("StubImage", content="BLACK", height=32, width=32, batch_size=1)
output = g.node("SaveImage", images=image.out(0))
# Prime the cache with a normal run.
client.run(g)
# Resubmit anonymously (no client_id) so output nodes are cache hits with no websocket client.
data = json.dumps({"prompt": g.finalize()}).encode('utf-8')
req = urllib.request.Request(f"http://{client.server_address}/prompt", data=data)
prompt_id = json.loads(urllib.request.urlopen(req).read())['prompt_id']
for _ in range(100):
job = client.get_job(prompt_id)
if job is not None and job['status'] not in ('pending', 'in_progress'):
break
time.sleep(0.1)
else:
raise AssertionError("Prompt did not complete in time")
assert job['status'] == 'completed'
assert output.id in job['outputs'], "Cached outputs must appear in job outputs without a client_id"
def _create_history_item(self, client, builder): def _create_history_item(self, client, builder):
g = GraphBuilder(prefix="offset_test") g = GraphBuilder(prefix="offset_test")
input_node = g.node( input_node = g.node(