nodejs/node · error · RuntimeError

Preprocessing failed: {command}

Error message

Preprocessing failed: {command}

What it means

preprocess_asm.py shells out to the located compiler (cl / clang / gcc) with -E -P (or MSVC equivalents) plus -I and -D flags to expand macros in an assembly source. If the compiler exits non-zero it dumps stderr and raises RuntimeError with the full command, because silently using partial preprocessor output would produce broken assembly.

Source

Thrown at deps/libffi/preprocess_asm.py:94

    include_dirs.append(str(output.parent))
    include_dirs = unique_paths(include_dirs)
    output.parent.mkdir(parents=True, exist_ok=True)

    if os.name == 'nt' and Path(compiler[0]).name.lower() in ('cl.exe', 'cl', 'clang-cl.exe', 'clang-cl'):
        command = compiler + ['/nologo', '/EP', '/TC']
        command += [f'/I{include_dir}' for include_dir in include_dirs]
        command += [f'/D{define}' for define in args.define]
        command += [input_path]
    else:
        command = compiler + ['-E', '-P', '-x', 'c']
        command += [f'-I{include_dir}' for include_dir in include_dirs]
        command += [f'-D{define}' for define in args.define]
        command += [input_path]

    result = subprocess.run(command, capture_output=True, text=True)
    if result.returncode != 0:
        sys.stderr.write(result.stderr)
        raise RuntimeError(f'Preprocessing failed: {" ".join(command)}')

    # Strip all preprocessor directives that assemblers can't handle
    # (e.g., armasm64.exe doesn't accept any # directives)
    # Remove lines starting with # (preprocessor output like #line, # 1 "file", etc.)
    lines = result.stdout.splitlines(keepends=True)
    cleaned_lines = [line for line in lines if not line.lstrip().startswith('#')]
    cleaned = ''.join(cleaned_lines)

    output.write_text(cleaned, encoding='utf-8')

    # If --assemble is specified, also run the assembler to produce an object file
    if args.assemble:
        assemble_output = Path(normalize_path(args.assemble))
        assemble_output.parent.mkdir(parents=True, exist_ok=True)

        armasm64 = find_armasm64()
        asm_command = [armasm64, '-nologo', '-g', str(output), '-o', str(assemble_output)]

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Read the stderr the script already printed — the real compiler error is there, not in the exception text.
  2. Add the missing include directory with another --include-dir, or the missing macro with --define.
  3. Make sure the compiler you resolved (CC/CXX) actually understands the source's preprocessor syntax.

Example fix

# before
python preprocess_asm.py --input src.S --output out.s
# after (missing include + macro)
python preprocess_asm.py --input src.S --output out.s --include-dir include --define HAVE_FFI_MMAP
Defensive patterns

Strategy: try-catch

Validate before calling

result = subprocess.run(command, capture_output=True, text=True)
if result.returncode != 0:
    raise SystemExit(f'preprocessor failed:\n{result.stderr}')

Try / catch

try:
    preprocess(args)
except RuntimeError as e:
    # the offending command is embedded in the message; compiler detail was already on stderr
    raise SystemExit(f'libffi preprocess failed: {e}') from None

Prevention

When it happens

Trigger: Raised when `subprocess.run(command, capture_output=True, text=True).returncode != 0` for the preprocessor invocation in preprocess(). The command is compiler + flags + input file.

Common situations: Missing #include the preprocessor can't find (include path not passed via --include-dir); a macro referenced by the .S file not defined via --define; wrong compiler for the syntax (gcc fed MSVC-flavored asm); corrupted/truncated source file; compiler crash.

Related errors


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