{"record":{"id":"29f371b10180b50d","repo":"affaan-m/ECC","slug":"unknown-dependency-dependency","errorCode":null,"errorMessage":"Unknown dependency: {dependency}","messagePattern":"Unknown dependency: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/workflow_graphs.py","lineNumber":83,"sourceCode":"    elif isinstance(value, dict):\n        for child in value.values():\n            yield from references_in(child)\n    elif isinstance(value, list):\n        for child in value:\n            yield from references_in(child)\n\n\ndef validate_graph(graph):\n    \"\"\"Verify dependencies and every declared input; endpoint schemas need live QA.\"\"\"\n    contents = graph['contents']\n    nodes, inputs = contents['nodes'], contents['schema']['input']\n    used = set()\n    for name, node in nodes.items():\n        if node['id'] != name:\n            raise ValueError(f'Node id mismatch: {name}')\n        for dependency in node.get('depends', []):\n            if dependency != 'input' and dependency not in nodes:\n                raise ValueError(f'Unknown dependency: {dependency}')\n    ancestors = {}\n\n    def visit(name, stack):\n        if name == 'input':\n            return set()\n        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':","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/workflow_graphs.py#L65-L101","documentation":"validate_graph verifies every node's 'depends' entries: each must be either the literal 'input' or the key of another node in the graph. A dependency naming a node that does not exist raises this ValueError, because the dependency could never be resolved at execution time.","triggerScenarios":"load_graph on a graph JSON where a node's depends list contains a typo, a deleted node's name, or a node added later but never registered in contents['nodes'].","commonSituations":"Renaming/removing a node without updating dependents' depends lists; hand-editing depends with a typo; merging two graphs where one references the other's nodes.","solutions":["Fix the depends entry to match an existing node key or 'input'","Remove the stale dependency if the referenced node was deleted","Add the missing node to contents['nodes'] if it should exist","Diff depends lists against node keys with a lint script before load_graph"],"exampleFix":"// before\n{\"render\": {\"id\": \"render\", \"depends\": [\"color_grade\", \"probs\"]}}\n// after\n{\"render\": {\"id\": \"render\", \"depends\": [\"color_grade\"]}}","handlingStrategy":"validation","validationCode":"def check_dependencies(graph):\n    nodes = graph['contents']['nodes']\n    for name, node in nodes.items():\n        for dep in node.get('depends', []):\n            if dep != 'input' and dep not in nodes:\n                raise ValueError(f'Unknown dependency: {dep}')","typeGuard":"def deps_resolvable(graph) -> bool:\n    nodes = graph['contents']['nodes']\n    return all(d == 'input' or d in nodes\n               for node in nodes.values() for d in node.get('depends', []))","tryCatchPattern":"try:\n    graph = load_graph(path)\nexcept ValueError as e:\n    if 'Unknown dependency' in str(e):\n        print(f'Dangling depends entry: {e}; fix or remove it')\n    else:\n        raise","preventionTips":["When deleting or renaming a node, grep for it in all depends lists","Add a dependency-lint step to CI for every graph JSON","Keep graphs small and generated from a single source of truth to avoid drift"],"tags":["validation","graph","dependency"],"backgroundTag":"missing-dependency","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"}