affaan-m/ECC · error · ValueError

Unwired workflow inputs

Error message

Unwired workflow inputs: {sorted(set(inputs) - used)}

What it means

validate_graph tracks which declared inputs are actually consumed by nodes (used set). After scanning node inputs/fields and the output section, if any declared input was never referenced, it raises ValueError listing the unwired input keys.

Solutions

  1. Reference the listed input in the appropriate node (e.g. a field like '{{input.<key>}}') or remove the key from the workflow's inputs object
  2. Check which node previously consumed the input and restore that dependency edge/reference
  3. Run the script's main entry again; the error message lists the exact unwired key names to fix

Example fix

// before
{"inputs": {"image": "...", "unused_hint": "..."}}
// after
{"inputs": {"image": "..."}}  // or add {{input.unused_hint}} to a node field
Defensive patterns

Strategy: validation

Validate before calling

declared = set(graph['inputs'])
used = set(re.findall(r"\{\{input\.(\w+)\}", json.dumps(graph)))
unwired = declared - used
assert not unwired, f'remove or wire inputs: {unwired}'

Try / catch

try:
    graph = load_graph(kind)
except ValueError as e:
    if str(e).startswith('Unwired workflow inputs'):
        keys = eval(str(e).split(': ', 1)[1])  # or parse safely
        for k in keys: graph['inputs'].pop(k, None)

Prevention

When it happens

Trigger: The workflow's inputs object declares a key (e.g. 'motion_hint') that no node references via ['input','motion_hint'] anywhere in input, fields, or output sections.

Common situations: Deleting the node that consumed an input without removing the input declaration; adding a required input to support a new node but forgetting to reference it; copying a workflow and pruning nodes but not inputs.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/b69c58efa9c7a2c9. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/workflow_graphs.py:109

        if name not in ancestors:
            deps = nodes[name].get('depends', [])
            ancestors[name] = set(deps).union(*(visit(dep, stack | {name}) for dep in deps))
        return ancestors[name]

    for name, node in nodes.items():
        reachable = visit(name, set())
        for ref in references_in({'input': node.get('input'), 'fields': node.get('fields')}):
            if ref[0] not in reachable:
                raise ValueError(f'{name} references undeclared dependency: {ref[0]}')
            if ref[0] == 'input':
                if len(ref) < 2 or ref[1] not in inputs:
                    raise ValueError('Unknown workflow input')
                used.add(ref[1])
    for ref in references_in(contents.get('output', {})):
        if ref[0] not in nodes:
            raise ValueError('Unknown output node')
    if used != set(inputs):
        raise ValueError(f'Unwired workflow inputs: {sorted(set(inputs) - used)}')


def load_graph(kind):
    if kind not in ('apply', 'apply-motion', 'distill', 'prop3d'):
        raise ValueError('Unknown workflow kind')
    graph = json.loads((WORKFLOWS / f'taste-{kind}.json').read_text())
    validate_graph(graph)
    return graph


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--kind', choices=('apply', 'apply-bundle', 'distill'), required=True)
    parser.add_argument('--config', type=Path, required=True)
    parser.add_argument('--out', type=Path, required=True)
    args = parser.parse_args()
    try:
        if args.kind == 'apply-bundle':

View on GitHub (pinned to 8321021c54)