nodejs/node · error · TypeError
Unknown AST node at key path '%s': %s
Error message
Unknown AST node at key path '%s': %s
What it means
Raised as a TypeError by CheckNode during checked .gyp evaluation when the AST contains a node type other than Dict, List, or Str. Gyp's strict check mode only permits string literals, lists, and dicts at the value level; anything else (numbers, booleans, None, name references, arithmetic, function calls) is rejected because gyp files are meant to be declarative data.
Source
Thrown at tools/gyp/pylib/gyp/input.py:218
+ " with key path '"
+ ".".join(keypath)
+ "'"
)
kp = list(keypath) # Make a copy of the list for descending this node.
kp.append(key)
dict[key] = CheckNode(value, kp)
return dict
elif isinstance(node, ast.List):
children = []
for index, child in enumerate(node.elts):
kp = list(keypath) # Copy list.
kp.append(repr(index))
children.append(CheckNode(child, kp))
return children
elif isinstance(node, ast.Str):
return node.s
else:
raise TypeError(
"Unknown AST node at key path '" + ".".join(keypath) + "': " + repr(node)
)
def LoadOneBuildFile(build_file_path, data, aux_data, includes, is_target, check):
if build_file_path in data:
return data[build_file_path]
if os.path.exists(build_file_path):
build_file_contents = open(build_file_path, encoding="utf-8").read()
else:
raise GypError(f"{build_file_path} not found (cwd: {os.getcwd()})")
build_file_data = None
try:
if check:
build_file_data = CheckedEval(build_file_contents)
else:View on GitHub (pinned to 1b2de5e052)
Solutions
- Convert non-string scalar values to quoted string literals (e.g. 3 -> '3', true -> 'true').
- Remove variable references and Python expressions; gyp files must be pure literal data in check mode.
- If you need computed values, use gyp variables and conditionals rather than inline expressions.
Example fix
// before
'targets': [{ 'target_name': 'foo', 'version': 3, 'enabled': true }]
// after
'targets': [{ 'target_name': 'foo', 'version': '3', 'enabled': 'true' }] Defensive patterns
Strategy: validation
Validate before calling
import ast
_ALLOWED = (ast.Dict, ast.List, ast.Str)
for fn in gyp_files:
tree = ast.parse(open(fn).read())
for node in ast.walk(tree):
if not isinstance(node, (ast.Module, ast.Expr)+_ALLOWED) and not isinstance(ast.dump(node), str):
pass
def check(node):
if isinstance(node, ast.Dict) or isinstance(node, ast.List):
return True
return isinstance(node, ast.Str) Type guard
import ast
def is_allowed_node(node) -> bool:
return isinstance(node, (ast.Dict, ast.List, ast.Str)) Prevention
- Use only string literals, lists, and dicts in checked .gyp files.
- Quote numeric/boolean values rather than using bare literals.
When it happens
Trigger: A .gyp file evaluated with check=True contains a numeric literal, a boolean, a bare identifier, a unary/binary expression, or a function call at a value position. CheckNode's isinstance chain falls through to the `else` at input.py:219.
Common situations: Using a number directly (e.g. 'version': 3) instead of a string ('version': '3'); referencing a variable by name; pasting Python expressions into a gyp file; using True/False/None literals.
Related errors
- Key '%s' repeated at level %s with key path '%s'
- %s not found (cwd: %s)
- %s does not evaluate to a dictionary.
- %s must not contain included_files key
- Unable to find targets in build file %s
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/9cf9944a21f8986c.
Report an issue: GitHub.