{"record":{"id":"8c03b739e7ded854","repo":"invoke-ai/InvokeAI","slug":"workflow-call-did-not-produce-any-child-executions","errorCode":null,"errorMessage":"Workflow call did not produce any child executions.","messagePattern":"Workflow call did not produce any child executions\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/session_processor/workflow_call_runtime.py","lineNumber":117,"sourceCode":"            self._session_runner._services.session_queue.save_queue_item_session(queue_item.item_id, queue_item.session)\n            for child_result in child_session_results:\n                child_queue_item = self._session_runner._services.session_queue.enqueue_workflow_call_child(\n                    parent_queue_item=queue_item,\n                    child_session=child_result.session,\n                    field_values=child_result.field_values,\n                )\n                enqueued_child_item_ids.append(child_queue_item.item_id)\n            queue_item.session.set_waiting_workflow_call_child_item_ids(enqueued_child_item_ids)\n            self._session_runner._services.session_queue.save_queue_item_session(queue_item.item_id, queue_item.session)\n            self._session_runner._services.session_queue.suspend_queue_item(queue_item.item_id, queue_item=queue_item)\n        except Exception as e:\n            if enqueued_child_item_ids:\n                self._session_runner._services.session_queue.delete_queue_items_by_id(enqueued_child_item_ids)\n            queue_item.session.end_waiting_on_workflow_call(status=\"failed\", error_message=str(e))\n            raise\n        queue_item.status = \"waiting\"\n        if child_queue_item is None:\n            raise ValueError(\"Workflow call did not produce any child executions.\")\n        return child_queue_item\n\n\nclass WorkflowCallQueueLifecycle:\n    \"\"\"Coordinates queue-visible child workflow execution and parent lifecycle transitions.\"\"\"\n\n    def __init__(self, session_runner: DefaultSessionRunner) -> None:\n        self._session_runner = session_runner\n\n    @staticmethod\n    def get_waiting_workflow_call_invocation(queue_item: SessionQueueItem) -> CallSavedWorkflowInvocation:\n        waiting_frame = queue_item.session.waiting_workflow_call\n        if waiting_frame is None:\n            raise ValueError(\"Execution state is not waiting on a workflow call.\")\n        invocation = queue_item.session.execution_graph.nodes.get(waiting_frame.prepared_call_node_id)\n        if not isinstance(invocation, CallSavedWorkflowInvocation):\n            raise ValueError(\"Waiting workflow call frame does not point to a call_saved_workflow invocation.\")\n        return invocation","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/session_processor/workflow_call_runtime.py#L99-L135","documentation":"After the boundary setup, the parent queue item is marked 'waiting' and a child queue item must exist. If child_queue_item is still None (no child was successfully enqueued and none of the earlier failures fired), the runtime raises ValueError because a workflow call with zero children is a no-op / broken state.","triggerScenarios":"begin_workflow_call_boundary completes enqueue/attach logic but the child queue item creation path left child_queue_item None — e.g. enqueue returned nothing or an internal branch skipped assignment while swallowing the failure.","commonSituations":"Downstream queue-service failures during enqueue that were partially handled; custom session-queue backends returning None; regressions in the WorkflowCallQueueLifecycle enqueue path; test setups with stubbed queue services.","solutions":["Inspect session-queue logs around the boundary call to find why enqueue produced no child queue item (usually a swallowed exception just above).","Verify the session-queue service implementation returns a real SessionQueueItem from enqueue; fix stubs/mocks in tests.","Catch this ValueError, end the workflow call with status 'failed' on the parent session, and re-raise so run_node surfaces the failure.","Upgrade/patch the coordinator so the enqueue failure path (which deletes enqueued children and re-raises) always fires instead of leaving child_queue_item None."],"exampleFix":"// before\nchild_queue_item = maybe_enqueue(...)  # may return None\n// after\nif child_queue_item is None:\n    queue_item.session.end_waiting_on_workflow_call(status=\"failed\", error_message=\"no child enqueued\")\n    raise ValueError(\"Workflow call did not produce any child executions.\")","handlingStrategy":"try-catch","validationCode":"if child_queue_item is None:\n    queue_item.session.end_waiting_on_workflow_call(status=\"failed\", error_message=\"no child enqueued\")\n    raise ValueError(\"Workflow call did not produce any child executions.\")","typeGuard":"def child_was_enqueued(item) -> bool:\n    return item is not None and getattr(item, \"item_id\", None) is not None","tryCatchPattern":"try:\n    child = begin_workflow_call_boundary(...)\nexcept ValueError as e:\n    if \"did not produce any child executions\" in str(e):\n        mark_parent_failed(queue_item, str(e)); raise","preventionTips":["Ensure enqueue paths always either return a queue item or raise","Log and alert on swallowed exceptions in the enqueue lifecycle","Test queue backends so None returns are impossible","Keep parent-session cleanup (end_waiting_on_workflow_call) on all failure paths"],"tags":["invokeai","queue","workflow-call","invariant-violation"],"backgroundTag":"workflow-call-no-child-executions","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}