affaan-m/ECC · error · ValueError
references undeclared dependency
Error message
{name} references undeclared dependency: {ref[0]} What it means
validate_graph collects every field/input reference in a node (via references_in) and requires each referenced source to be inside the node's transitive depends set (reachable). If a reference names a node that is not a (transitive) dependency, the node would read data the graph never provides, so ValueError is raised.
Solutions
- Add the referenced node's name to the consuming node's depends array in the workflow JSON
- Check spelling of the reference against the exact node keys in nodes
- If the reference is transitively available, verify each intermediate edge is present in depends chains
- Remove the stale reference if the data is no longer needed
Example fix
// before
{"name": "apply", "depends": ["upscale"], "input": "{{distill.output}}"}
// after
{"name": "apply", "depends": ["upscale", "distill"], "input": "{{distill.output}}"} Defensive patterns
Strategy: validation
Validate before calling
def deps_declared(node, nodes):
reachable = set()
stack = [node['name']]
while stack:
n = stack.pop()
for d in nodes[n].get('depends', []):
if d not in reachable:
reachable.add(d); stack.append(d)
refs = re.findall(r"\{\{(\w+)\.", json.dumps(node))
return all(r in reachable for r in refs) Try / catch
try:
graph = load_graph(kind)
except ValueError as e:
if 'references undeclared dependency' in str(e):
node, ref = ... # parse names from message
graph['nodes'][node]['depends'].append(ref) Prevention
- Add the depends entry in the same edit that adds a cross-node reference
- Use a template/lint rule: every {{node.field}} reference must appear in depends
- Review workflow diffs for asymmetric reference/depends changes
When it happens
Trigger: A node's input/fields entries reference e.g. ['distill','embedding'] while the node's depends array omits 'distill' (or omits an intermediate node through which it would be reachable).
Common situations: Adding a reference to another node's output but forgetting to add that node to depends; removing a depends entry while leaving the references; typos in node names in references.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Dependency cycle
- Unknown output node
- Unknown workflow input
- Unwired workflow inputs
- Announcements discussion category is required
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/abdd2c94103aa4be.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/workflow_graphs.py:100
if dependency != 'input' and dependency not in nodes:
raise ValueError(f'Unknown dependency: {dependency}')
ancestors = {}
def visit(name, stack):
if name == 'input':
return set()
if name in stack:
raise ValueError('Dependency cycle')
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
View on GitHub (pinned to 8321021c54)