{"record":{"id":"18ea1b4f0b02b6bc","repo":"affaan-m/ECC","slug":"unknown-output-node","errorCode":null,"errorMessage":"Unknown output node","messagePattern":"Unknown output node","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/workflow_graphs.py","lineNumber":107,"sourceCode":"        if name in stack:\n            raise ValueError('Dependency cycle')\n        if name not in ancestors:\n            deps = nodes[name].get('depends', [])\n            ancestors[name] = set(deps).union(*(visit(dep, stack | {name}) for dep in deps))\n        return ancestors[name]\n\n    for name, node in nodes.items():\n        reachable = visit(name, set())\n        for ref in references_in({'input': node.get('input'), 'fields': node.get('fields')}):\n            if ref[0] not in reachable:\n                raise ValueError(f'{name} references undeclared dependency: {ref[0]}')\n            if ref[0] == 'input':\n                if len(ref) < 2 or ref[1] not in inputs:\n                    raise ValueError('Unknown workflow input')\n                used.add(ref[1])\n    for ref in references_in(contents.get('output', {})):\n        if ref[0] not in nodes:\n            raise ValueError('Unknown output node')\n    if used != set(inputs):\n        raise ValueError(f'Unwired workflow inputs: {sorted(set(inputs) - used)}')\n\n\ndef load_graph(kind):\n    if kind not in ('apply', 'apply-motion', 'distill', 'prop3d'):\n        raise ValueError('Unknown workflow kind')\n    graph = json.loads((WORKFLOWS / f'taste-{kind}.json').read_text())\n    validate_graph(graph)\n    return graph\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument('--kind', choices=('apply', 'apply-bundle', 'distill'), required=True)\n    parser.add_argument('--config', type=Path, required=True)\n    parser.add_argument('--out', type=Path, required=True)\n    args = parser.parse_args()","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/workflow_graphs.py#L89-L125","documentation":"The workflow's output section must reference existing node names. validate_graph iterates references_in(contents['output']) and raises ValueError('Unknown output node') if any referenced first element is not a key of nodes.","triggerScenarios":"contents['output'] contains e.g. ['apply_final','...'] but the nodes map has 'apply' or 'apply-motion' — a stale or misspelled node reference in the workflow's output declaration.","commonSituations":"Renaming the final node without updating the output section; editing the output by hand in the taste-<kind>.json workflow file; switching a workflow kind and reusing another workflow's output block.","solutions":["Update the output reference to match an existing node name in nodes","Rename the node itself to the name used in output if that was the intent","Diff the workflow JSON against a working sibling (e.g. taste-apply.json) to spot the stale name","Run load_graph again after the fix; any remaining mismatch will surface on the next validation pass"],"exampleFix":"// before\n{\"output\": {\"result\": \"{{apply_result.video}}\"}}  // no node 'apply_result'\n// after\n{\"output\": {\"result\": \"{{apply.video}}\"}}","handlingStrategy":"validation","validationCode":"nodes = set(graph['nodes'])\nfor ref in re.findall(r\"\\{\\{(\\w+)\\.\", json.dumps(graph.get('output', {}))):\n    assert ref in nodes, f'unknown output node: {ref}'","typeGuard":null,"tryCatchPattern":"try:\n    graph = load_graph(kind)\nexcept ValueError as e:\n    if str(e) == 'Unknown output node':\n        # fix the output section to point at an existing node\n        ...","preventionTips":["Update the output section whenever renaming the final node","Generate the output block from the node names programmatically instead of by hand","Keep one canonical workflow file per kind and derive variants from it"],"tags":["graph","configuration","output-validation"],"backgroundTag":"record-not-found","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}