nodejs/node · error · GypError
%s must not contain included_files key
Error message
%s must not contain included_files key
What it means
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.
Source
Thrown at tools/gyp/pylib/gyp/input.py:410
# Already loaded.
return False
data["target_build_files"].add(build_file_path)
gyp.DebugOutput(
gyp.DEBUG_INCLUDES, "Loading Target Build File '%s'", build_file_path
)
build_file_data = LoadOneBuildFile(
build_file_path, data, aux_data, includes, True, check
)
# Store DEPTH for later use in generators.
build_file_data["_DEPTH"] = depth
# Set up the included_files key indicating which .gyp files contributed to
# this target dict.
if "included_files" in build_file_data:
raise GypError(build_file_path + " must not contain included_files key")
included = GetIncludedBuildFiles(build_file_path, aux_data)
build_file_data["included_files"] = []
for included_file in included:
# included_file is relative to the current directory, but it needs to
# be made relative to build_file_path's directory.
included_relative = gyp.common.RelativePath(
included_file, os.path.dirname(build_file_path)
)
build_file_data["included_files"].append(included_relative)
# Do a first round of toolsets expansion so that conditions can be defined
# per toolset.
ProcessToolsetsInDict(build_file_data)
# Apply "pre"/"early" variable expansions and condition evaluations.
ProcessVariablesAndConditionsInDict(
build_file_data, PHASE_EARLY, variables, build_file_pathView on GitHub (pinned to 1b2de5e052)
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.
Example fix
// before (foo.gyp)
{
'included_files': ['common.gypi'],
'targets': [ ... ]
}
// after
{
'includes': ['common.gypi'],
'targets': [ ... ]
} Defensive patterns
Strategy: validation
Validate before calling
RESERVED = {'included_files'}
for k in build_file_data:
if k in RESERVED:
raise ValueError(f'{k} is reserved; remove it from the .gyp file') Type guard
def free_of_reserved_keys(data) -> bool:
return 'included_files' not in data Prevention
- Never add 'included_files' to source .gyp files; use 'includes'.
- Lint for reserved keys in CI.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Key '%s' repeated at level %s with key path '%s'
- %s does not evaluate to a dictionary.
- Unable to find targets in build file %s
- Unable to open file %s
- Unknown AST node at key path '%s': %s
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/ff83e6efe95d75ca.
Report an issue: GitHub.