{"record":{"id":"92ddb92cb7b3e61c","repo":"nodejs/node","slug":"s-does-not-evaluate-to-a-dictionary","errorCode":null,"errorMessage":"%s does not evaluate to a dictionary.","messagePattern":"(.+?) does not evaluate to a dictionary\\.","errorType":"exception","errorClass":"GypError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":246,"sourceCode":"        build_file_contents = open(build_file_path, encoding=\"utf-8\").read()\n    else:\n        raise GypError(f\"{build_file_path} not found (cwd: {os.getcwd()})\")\n\n    build_file_data = None\n    try:\n        if check:\n            build_file_data = CheckedEval(build_file_contents)\n        else:\n            build_file_data = eval(build_file_contents, {\"__builtins__\": {}}, None)\n    except SyntaxError as e:\n        e.filename = build_file_path\n        raise\n    except Exception as e:\n        gyp.common.ExceptionAppend(e, \"while reading \" + build_file_path)\n        raise\n\n    if not isinstance(build_file_data, dict):\n        raise GypError(\"%s does not evaluate to a dictionary.\" % build_file_path)\n\n    data[build_file_path] = build_file_data\n    aux_data[build_file_path] = {}\n\n    # Scan for includes and merge them in.\n    if \"skip_includes\" not in build_file_data or not build_file_data[\"skip_includes\"]:\n        try:\n            if is_target:\n                LoadBuildFileIncludesIntoDict(\n                    build_file_data, build_file_path, data, aux_data, includes, check\n                )\n            else:\n                LoadBuildFileIncludesIntoDict(\n                    build_file_data, build_file_path, data, aux_data, None, check\n                )\n        except Exception as e:\n            gyp.common.ExceptionAppend(\n                e, \"while reading includes of \" + build_file_path","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L228-L264","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the .gyp file's top-level construct is a dict literal, e.g. { 'targets': [ ... ] }.","If the file contains a bare list, wrap it as { 'targets': <that list> }.","Validate the file evaluates to a dict before running gyp (e.g. a quick AST/eval check)."],"exampleFix":"// before (foo.gyp)\n[ { 'target_name': 'foo', 'type': 'none' } ]\n// after\n{\n  'targets': [\n    { 'target_name': 'foo', 'type': 'none' }\n  ]\n}","handlingStrategy":"validation","validationCode":"data = eval(open('foo.gyp').read(), {'__builtins__': {}}, None)\nif not isinstance(data, dict):\n    raise ValueError('foo.gyp must evaluate to a dictionary')","typeGuard":"def evaluates_to_dict(data) -> bool:\n    return isinstance(data, dict)","tryCatchPattern":null,"preventionTips":["Ensure every .gyp file's top-level construct is a dict literal.","Start new .gyp files from a template with the correct root structure."],"tags":["gyp","input","schema","config","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}