{"record":{"id":"ff83e6efe95d75ca","repo":"nodejs/node","slug":"s-must-not-contain-included-files-key","errorCode":null,"errorMessage":"%s must not contain included_files key","messagePattern":"(.+?) must not contain included_files key","errorType":"exception","errorClass":"GypError","httpStatus":null,"severity":"error","filePath":"tools/gyp/pylib/gyp/input.py","lineNumber":410,"sourceCode":"            # Already loaded.\n            return False\n        data[\"target_build_files\"].add(build_file_path)\n\n    gyp.DebugOutput(\n        gyp.DEBUG_INCLUDES, \"Loading Target Build File '%s'\", build_file_path\n    )\n\n    build_file_data = LoadOneBuildFile(\n        build_file_path, data, aux_data, includes, True, check\n    )\n\n    # Store DEPTH for later use in generators.\n    build_file_data[\"_DEPTH\"] = depth\n\n    # Set up the included_files key indicating which .gyp files contributed to\n    # this target dict.\n    if \"included_files\" in build_file_data:\n        raise GypError(build_file_path + \" must not contain included_files key\")\n\n    included = GetIncludedBuildFiles(build_file_path, aux_data)\n    build_file_data[\"included_files\"] = []\n    for included_file in included:\n        # included_file is relative to the current directory, but it needs to\n        # be made relative to build_file_path's directory.\n        included_relative = gyp.common.RelativePath(\n            included_file, os.path.dirname(build_file_path)\n        )\n        build_file_data[\"included_files\"].append(included_relative)\n\n    # Do a first round of toolsets expansion so that conditions can be defined\n    # per toolset.\n    ProcessToolsetsInDict(build_file_data)\n\n    # Apply \"pre\"/\"early\" variable expansions and condition evaluations.\n    ProcessVariablesAndConditionsInDict(\n        build_file_data, PHASE_EARLY, variables, build_file_path","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/tools/gyp/pylib/gyp/input.py#L392-L428","documentation":"Raised as a GypError by LoadTargetBuildFile when a .gyp file already contains an 'included_files' key at the top level. gyp itself populates 'included_files' to track which .gypi files contributed to a target, so a user-supplied key of that name would collide and corrupt that bookkeeping.","triggerScenarios":"A target .gyp file includes an 'included_files' key in its top-level dict. gyp detects this at input.py:413 and refuses to overwrite it.","commonSituations":"Manually adding an 'included_files' key (mistaking it for a user-facing feature); copy-pasting gyp's internal output back into a source .gyp; a tool that round-trips gyp's processed dicts into source files.","solutions":["Remove the 'included_files' key from the .gyp file; it is reserved for gyp's internal use.","If you need to list include files, use the 'includes' key instead.","Audit the file for any keys gyp manages internally (included_files) and remove them."],"exampleFix":"// before (foo.gyp)\n{\n  'included_files': ['common.gypi'],\n  'targets': [ ... ]\n}\n// after\n{\n  'includes': ['common.gypi'],\n  'targets': [ ... ]\n}","handlingStrategy":"validation","validationCode":"RESERVED = {'included_files'}\nfor k in build_file_data:\n    if k in RESERVED:\n        raise ValueError(f'{k} is reserved; remove it from the .gyp file')","typeGuard":"def free_of_reserved_keys(data) -> bool:\n    return 'included_files' not in data","tryCatchPattern":null,"preventionTips":["Never add 'included_files' to source .gyp files; use 'includes'.","Lint for reserved keys in CI."],"tags":["gyp","input","reserved-key","config","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}