nodejs/node · error · GypError

Call to '%s' returned exit status %d while in %s.

Error message

Call to '%s' returned exit status %d while in %s.

What it means

For <!() command expansions, GYP runs the command via subprocess.run and, if result.returncode is greater than zero, raises this GypError with the command, the exit status, and the build file. stderr is intentionally not captured so it streams to the console, which usually tells you why the command failed. The command's stdout (only produced on success) is what gets substituted.

Source

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

                    # Fix up command with platform specific workarounds.
                    contents = FixupPlatformCommand(contents)
                    try:
                        # stderr will be printed no matter what
                        result = subprocess.run(
                            contents,
                            stdout=subprocess.PIPE,
                            shell=use_shell,
                            cwd=build_file_dir,
                            check=False,
                        )
                    except Exception as e:
                        raise GypError(
                            "%s while executing command '%s' in %s"
                            % (e, contents, build_file)
                        )

                    if result.returncode > 0:
                        raise GypError(
                            "Call to '%s' returned exit status %d while in %s."
                            % (contents, result.returncode, build_file)
                        )
                    replacement = result.stdout.decode("utf-8").rstrip()

                cached_command_results[cache_key] = replacement
            else:
                gyp.DebugOutput(
                    gyp.DEBUG_VARIABLES,
                    "Had cache value for command '%s' in directory '%s'",
                    contents,
                    build_file_dir,
                )
                replacement = cached_value

        elif contents not in variables:
            if contents[-1] in ["!", "/"]:
                # In order to allow cross-compiles (nacl) to happen more naturally,

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Look immediately above the GypError in the log — stderr was printed live and explains the failure.
  2. Re-run the exact command (from the .gyp file's directory) to reproduce and fix the underlying tool/script.
  3. Make the command tolerant of missing inputs if that is intended, or fix the inputs so it succeeds.
  4. Ensure required env vars are exported before invoking gyp.

Example fix

// before — script exits 1 on missing template
'version': '<!(./gen_version.py)',
// after — pass the template path the script expects
'version': '<!(./gen_version.py --template ./tmpl.h)',
Defensive patterns

Strategy: validation

Validate before calling

import subprocess
rc = subprocess.run(cmd, shell=True, cwd=build_file_dir).returncode
assert rc == 0, f'<!() command exited {rc}: {cmd}'

Type guard

def command_succeeds(cmd: str, cwd: str) -> bool:
    import subprocess
    return subprocess.run(cmd, shell=True, cwd=cwd).returncode == 0

Try / catch

try:
    gyp.process_build_file(...)
except gyp.input.GypError as e:
    if 'returned exit status' in str(e):
        log_full_stderr_context(e)

Prevention

When it happens

Trigger: A '<!(cmd)' expansion runs a script/program that exits non-zero — the codegen tool failed, the script hit an internal error, missing input file, wrong CLI flags, or a flaky network call inside the command.

Common situations: A codegen script that errors on missing input; wrong CLI flags after a tool upgrade; a script that depends on env vars (PATH, OUT_DIR) not set in the gyp environment; flaky commands during distributed builds; a helper that returns non-zero on warnings-as-errors.

Related errors


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