nodejs/node · error · GypError

The 'environment' for 'run_as' in target %s in file %s shoul

Error message

The 'environment' for 'run_as' in target %s in file %s should be a dictionary.

What it means

The optional 'environment' under run_as must be a dict of variable name to value. Other truthy types are rejected because the runner iterates the dict to set subprocess environment variables.

Source

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

    if not action:
        raise GypError(
            "The 'run_as' in target %s from file %s must have an "
            "'action' section." % (target_name, build_file)
        )
    if not isinstance(action, list):
        raise GypError(
            "The 'action' for 'run_as' in target %s from file %s "
            "must be a list." % (target_name, build_file)
        )
    working_directory = run_as.get("working_directory")
    if working_directory and not isinstance(working_directory, str):
        raise GypError(
            "The 'working_directory' for 'run_as' in target %s "
            "in file %s should be a string." % (target_name, build_file)
        )
    environment = run_as.get("environment")
    if environment and not isinstance(environment, dict):
        raise GypError(
            "The 'environment' for 'run_as' in target %s "
            "in file %s should be a dictionary." % (target_name, build_file)
        )


def ValidateActionsInTarget(target, target_dict, build_file):
    """Validates the inputs to the actions in a target."""
    target_name = target_dict.get("target_name")
    actions = target_dict.get("actions", [])
    for action in actions:
        action_name = action.get("action_name")
        if not action_name:
            raise GypError(
                "Anonymous action in target %s.  "
                "An action must have an 'action_name' field." % target_name
            )
        inputs = action.get("inputs", None)
        if inputs is None:

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Express environment as a dict { 'VAR': 'value' }.
  2. Use string values for each variable.
  3. Re-run gyp.

Example fix

// before
'run_as': { 'action': ['app'], 'environment': ['FOO=bar', 'BAZ=qux'] },
// after
'run_as': { 'action': ['app'], 'environment': { 'FOO': 'bar', 'BAZ': 'qux' } },
Defensive patterns

Strategy: type-guard

Validate before calling

ra = target_dict.get('run_as')
if isinstance(ra, dict):
    env = ra.get('environment')
    if env and not isinstance(env, dict):
        raise TypeError('run_as.environment must be a dict')

Type guard

def run_as_env_is_dict(target_dict: dict) -> bool:
    ra = target_dict.get('run_as')
    if not isinstance(ra, dict):
        return True
    env = ra.get('environment')
    return env is None or isinstance(env, dict)

Prevention

When it happens

Trigger: run_as['environment'] is truthy but isinstance(environment, dict) is False.

Common situations: Encoding environment as a list of 'K=V' strings or a single string instead of a mapping; misreading the schema from a different build system.

Related errors


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