affaan-m/ECC · error · ValueError
Node id mismatch
Error message
Node id mismatch: {name} What it means
validate_graph checks that each entry key in contents['nodes'] matches that node's declared 'id' field. A mismatch means the graph JSON's node map key and internal id have drifted — references by name would resolve incorrectly, so load_graph refuses the graph with this ValueError.
Solutions
- Set the node's 'id' field to exactly match its key in the nodes dict (or vice versa)
- Re-generate the graph JSON from the canonical builder to restore key/id consistency
- Run a pre-check comparing each node key to node['id'] before load_graph
Example fix
// before
{"nodes": {"probe": {"id": "probe_v2", ...}}}
// after
{"nodes": {"probe": {"id": "probe", ...}}} Defensive patterns
Strategy: validation
Validate before calling
def check_node_ids(graph):
for name, node in graph['contents']['nodes'].items():
if node['id'] != name:
raise ValueError(f'Node id mismatch: {name}') Type guard
def ids_consistent(graph) -> bool:
nodes = graph['contents']['nodes']
return all(node.get('id') == name for name, node in nodes.items()) Try / catch
try:
graph = load_graph(path)
except ValueError as e:
if 'Node id mismatch' in str(e):
print(f'Graph JSON inconsistent, fix key/id: {e}')
else:
raise Prevention
- Rename nodes with a script that updates both the dict key and the id field
- Validate graph JSON with a schema/lint in CI before load_graph
- Avoid hand-editing generated graphs; regenerate from the builder
When it happens
Trigger: Loading a hand-edited or generated graph JSON where a node's 'id' field was changed (or its dict key renamed) so node['id'] != key, then calling load_graph.
Common situations: Renaming a node in one place (key or id) but not the other; a code generator emitting inconsistent ids; merge conflict leaving key/id divergent.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- -32602
- artifact path must be a non-empty relative path
- assets must be a nonempty list
- built an invalid spec
- Canonical session snapshot must be an object
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/325c23f5c6c2cdad.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/workflow_graphs.py:80
def references_in(value):
if isinstance(value, str) and value.startswith('$'):
yield value[1:].split('.')
elif isinstance(value, dict):
for child in value.values():
yield from references_in(child)
elif isinstance(value, list):
for child in value:
yield from references_in(child)
def validate_graph(graph):
"""Verify dependencies and every declared input; endpoint schemas need live QA."""
contents = graph['contents']
nodes, inputs = contents['nodes'], contents['schema']['input']
used = set()
for name, node in nodes.items():
if node['id'] != name:
raise ValueError(f'Node id mismatch: {name}')
for dependency in node.get('depends', []):
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')}):View on GitHub (pinned to 8321021c54)