From 4a9f0663b78d6b5136bd0cd8a84cc6b01addc537 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 10:09:56 +0000 Subject: [PATCH] fix: include workflow in GET /api/jobs/{id} for running/pending jobs Jobs API single-job detail lookups only embedded the workflow for terminal (history) jobs; running and pending jobs went through normalize_queue_item, which never carried it even though the prompt and extra_data are already available on the queue tuple. The frontend caches job detail responses by job id and never refetches once cached, so opening a still-running or queued job as a workflow failed, and stayed broken permanently once the job finished, because the cached entry from while it was running never had a workflow to begin with. Fixes #14995 --- comfy_execution/jobs.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/comfy_execution/jobs.py b/comfy_execution/jobs.py index 34c06363b..d9574932a 100644 --- a/comfy_execution/jobs.py +++ b/comfy_execution/jobs.py @@ -183,15 +183,20 @@ def is_text_preview(media_type: str, item: dict) -> bool: return any(filename.endswith(ext) for ext in TEXT_EXTENSIONS) -def normalize_queue_item(item: tuple, status: str) -> dict: +def normalize_queue_item(item: tuple, status: str, include_workflow: bool = False) -> dict: """Convert queue item tuple to unified job dict. Expects item with sensitive data already removed (5 elements). + + include_workflow embeds the full prompt/extra_data (as 'workflow') the + same way normalize_history_item(include_outputs=True) does. It's only + set for single-job detail lookups (get_job), not the list endpoint, + to keep list responses lightweight. """ - priority, prompt_id, _, extra_data, _ = item + priority, prompt_id, prompt, extra_data, _ = item create_time, workflow_id = _extract_job_metadata(extra_data) - return prune_dict({ + job = prune_dict({ 'id': prompt_id, 'status': status, 'priority': priority, @@ -200,6 +205,14 @@ def normalize_queue_item(item: tuple, status: str) -> dict: 'workflow_id': workflow_id, }) + if include_workflow: + job['workflow'] = { + 'prompt': prompt, + 'extra_data': extra_data, + } + + return job + def normalize_history_item(prompt_id: str, history_item: dict, include_outputs: bool = False) -> dict: """Convert history item dict to unified job dict. @@ -379,11 +392,11 @@ def get_job(prompt_id: str, running: list, queued: list, history: dict) -> Optio for item in running: if item[1] == prompt_id: - return normalize_queue_item(item, JobStatus.IN_PROGRESS) + return normalize_queue_item(item, JobStatus.IN_PROGRESS, include_workflow=True) for item in queued: if item[1] == prompt_id: - return normalize_queue_item(item, JobStatus.PENDING) + return normalize_queue_item(item, JobStatus.PENDING, include_workflow=True) return None