nodejs/node · error · GypError

%s does not evaluate to a dictionary.

Error message

%s does not evaluate to a dictionary.

What it means

Raised as a GypError by LoadOneBuildFile after a .gyp file is read and evaluated but the resulting top-level value is not a dictionary. A .gyp file must evaluate to a dict (with keys like 'targets', 'includes', 'variables'); any other top-level expression is a structural error.

Source

Thrown at tools/gyp/pylib/gyp/input.py:246

        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:
            build_file_data = eval(build_file_contents, {"__builtins__": {}}, None)
    except SyntaxError as e:
        e.filename = build_file_path
        raise
    except Exception as e:
        gyp.common.ExceptionAppend(e, "while reading " + build_file_path)
        raise

    if not isinstance(build_file_data, dict):
        raise GypError("%s does not evaluate to a dictionary." % build_file_path)

    data[build_file_path] = build_file_data
    aux_data[build_file_path] = {}

    # Scan for includes and merge them in.
    if "skip_includes" not in build_file_data or not build_file_data["skip_includes"]:
        try:
            if is_target:
                LoadBuildFileIncludesIntoDict(
                    build_file_data, build_file_path, data, aux_data, includes, check
                )
            else:
                LoadBuildFileIncludesIntoDict(
                    build_file_data, build_file_path, data, aux_data, None, check
                )
        except Exception as e:
            gyp.common.ExceptionAppend(
                e, "while reading includes of " + build_file_path

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Ensure the .gyp file's top-level construct is a dict literal, e.g. { 'targets': [ ... ] }.
  2. If the file contains a bare list, wrap it as { 'targets': <that list> }.
  3. Validate the file evaluates to a dict before running gyp (e.g. a quick AST/eval check).

Example fix

// before (foo.gyp)
[ { 'target_name': 'foo', 'type': 'none' } ]
// after
{
  'targets': [
    { 'target_name': 'foo', 'type': 'none' }
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

data = eval(open('foo.gyp').read(), {'__builtins__': {}}, None)
if not isinstance(data, dict):
    raise ValueError('foo.gyp must evaluate to a dictionary')

Type guard

def evaluates_to_dict(data) -> bool:
    return isinstance(data, dict)

Prevention

When it happens

Trigger: A .gyp file whose top-level expression is not a dict — e.g. a bare list, a string, or an expression statement. After eval, isinstance(build_file_data, dict) is False at input.py:248.

Common situations: A .gyp file containing only a list of targets instead of { 'targets': [...] }; a file reduced to a bare expression by a bad edit; accidentally creating a .gyp from a template that outputs the wrong root structure.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/92ddb92cb7b3e61c. Report an issue: GitHub.