{"record":{"id":"921fa7a343cb2340","repo":"invoke-ai/InvokeAI","slug":"call-saved-workflow-input-input-name-is-not-ex","errorCode":null,"errorMessage":"call_saved_workflow input '{input_name}' is not exposed by the selected workflow","messagePattern":"call_saved_workflow input '(.+?)' is not exposed by the selected workflow","errorType":"validation","errorClass":"InvalidWorkflowInputError","httpStatus":400,"severity":"error","filePath":"invokeai/app/services/shared/workflow_graph_builder.py","lineNumber":120,"sourceCode":"    for field in workflow_exposed_fields:\n        if not _is_mapping(field):\n            continue\n        node_id = field.get(\"nodeId\")\n        field_name = field.get(\"fieldName\")\n        if isinstance(node_id, str) and isinstance(field_name, str):\n            fallback_inputs.add(_build_dynamic_input_name(node_id, field_name))\n\n    return fallback_inputs\n\n\ndef apply_workflow_inputs_to_workflow(workflow: MutableMapping[str, Any], workflow_inputs: Mapping[str, Any]) -> None:\n    if not workflow_inputs:\n        return\n\n    allowed_inputs = get_exposed_workflow_input_names(workflow)\n    for input_name, value in workflow_inputs.items():\n        if input_name not in allowed_inputs:\n            raise InvalidWorkflowInputError(\n                f\"call_saved_workflow input '{input_name}' is not exposed by the selected workflow\"\n            )\n\n        node_id, field_name = parse_call_saved_workflow_dynamic_input(input_name)\n        workflow_nodes = workflow.get(\"nodes\", [])\n        if not isinstance(workflow_nodes, list):\n            raise InvalidWorkflowInputError(\n                f\"call_saved_workflow input '{input_name}' targets missing child workflow node '{node_id}'\"\n            )\n        matching_node = next(\n            (\n                node\n                for node in workflow_nodes\n                if _is_mapping(node)\n                and _is_mapping(node.get(\"data\"))\n                and node.get(\"id\") == node_id\n                and node[\"data\"].get(\"id\") == node_id\n            ),","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/shared/workflow_graph_builder.py#L102-L138","documentation":"When applying call_saved_workflow dynamic inputs to a saved child workflow, an input name was supplied that the workflow does not expose as an exposed/public input. The builder only allows setting fields that the workflow author explicitly exposed, to prevent tampering with internal graph structure.","triggerScenarios":"Calling apply_workflow_inputs_to_workflow (directly or via build_child_workflow_session_results / build_batch_child_workflow_session_results / apply_workflow_inputs_to_graph) with a workflow_inputs key not returned by get_exposed_workflow_input_names(workflow).","commonSituations":"Caller renamed or un-exposed a field in the saved workflow but batch/config still passes the old input name; typo in the input key; targeting a node's internal field that was never checked 'exposed' in the workflow editor.","solutions":["Open the saved workflow in the workflow editor and mark the target field as exposed (field value / exposed input).","Fix the input key in the calling code to exactly match an exposed input name (parse_call_saved_workflow_dynamic_input format).","Remove stale inputs from the batch/prompt config for fields that no longer exist in the workflow."],"exampleFix":"// before\ninputs = {\"internal_hidden_field\": \"x\"}\n// after: use an exposed input name\ninputs = {\"call_saved_workflow:13:positive_prompt\": \"a cat\"}","handlingStrategy":"validation","validationCode":"from invokeai.app.services.shared.workflow_graph_builder import get_exposed_workflow_input_names\nallowed = set(get_exposed_workflow_input_names(workflow))\nbad = set(workflow_inputs) - allowed\nif bad:\n    raise ValueError(f\"inputs not exposed by workflow: {sorted(bad)}\")","typeGuard":"def inputs_are_exposed(workflow: dict, inputs: dict) -> bool:\n    allowed = set(get_exposed_workflow_input_names(workflow))\n    return all(name in allowed for name in inputs)","tryCatchPattern":"from invokeai.app.services.shared.workflow_graph_builder import InvalidWorkflowInputError\ntry:\n    results = build_child_workflow_session_results(workflow, workflow_inputs)\nexcept InvalidWorkflowInputError as e:\n    log.warning(\"dropping invalid workflow input: %s\", e)\n    results = build_child_workflow_session_results(workflow, {})  # fallback: run without dynamic inputs","preventionTips":["Expose fields in the workflow editor before referencing them as call_saved_workflow inputs.","Derive input keys from get_exposed_workflow_input_names at runtime instead of hardcoding.","Re-validate saved batch configs whenever the underlying workflow is edited.","Avoid hand-writing 'call_saved_workflow:<node>:<field>' strings; use the parse helper round-trip."],"tags":["workflow","validation","input"],"backgroundTag":"workflow-input-not-exposed","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}