nodejs/node · error · RuntimeError

No libnode.so to install!

Error message

No libnode.so to install!

What it means

When node is built as a shared library (configure variable node_shared=true, on non-Windows/non-z/OS), tools/install.py looks for the built libnode.<shlib_suffix> in build_dir/ and build_dir/lib/ (ninja vs make output locations). If neither exists it raises RuntimeError, because there is no artifact to install.

Source

Thrown at tools/install.py:194

      # install libnode.version.so
      so_name = 'libnode.' + re.sub(r'\.x$', '.so', options.variables.get('shlib_suffix'))
      action(options, [os.path.join(output_prefix, so_name)], options.variables.get('libdir') + '/' + so_name)

      # create symlink of libnode.so -> libnode.version.so (C++ addons compat)
      link_path = abspath(options.install_path, 'lib/libnode.so')
      try_symlink(options, so_name, link_path)
    else:
      # Ninja and Makefile generators output the library in different directories;
      # find out which one we have, and install first found
      output_lib_name = 'libnode.' + options.variables.get('shlib_suffix')
      output_lib_candidate_paths = [
        os.path.join(options.build_dir, output_lib_name),
        os.path.join(options.build_dir, "lib", output_lib_name),
      ]
      try:
        output_lib = next(filter(os.path.exists, output_lib_candidate_paths))
      except StopIteration as not_found:
        raise RuntimeError("No libnode.so to install!") from not_found
      action(options, [output_lib],
             os.path.join(options.variables.get('libdir'), output_lib_name))

  action(options, [os.path.join(options.v8_dir, 'tools/gdbinit')], 'share/doc/node/')
  action(options, [os.path.join(options.v8_dir, 'tools/lldb_commands.py')], 'share/doc/node/')

  if 'openbsd' in sys.platform:
    action(options, ['doc/node.1'], 'man/man1/')
  else:
    action(options, ['doc/node.1'], 'share/man/man1/')

  if 'true' == options.variables.get('node_install_npm'):
    npm_files(options, action)

  if 'true' == options.variables.get('node_install_corepack'):
    corepack_files(options, action)

  headers(options, action)

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Build the shared library first with the same configuration, e.g. `make -j$(nproc) out/Release/libnode.so.71` (match your shlib_suffix).
  2. Verify the artifact exists: `ls out/Release/libnode.* out/Release/lib/libnode.*`.
  3. Pass the correct --build-dir (the directory that actually contains the built lib).

Example fix

// before
python tools/install.py install --build-dir=out/Debug   # never built Debug
// after
make -j$(nproc) out/Release/libnode.so.71
python tools/install.py install --build-dir=out/Release
Defensive patterns

Strategy: validation

Validate before calling

import os, glob
bd=options.build_dir; suf=options.variables.get('shlib_suffix')
cands=[os.path.join(bd,f'libnode.{suf}'), os.path.join(bd,'lib',f'libnode.{suf}')]
assert any(os.path.exists(c) for c in cands), f'no libnode.{suf} in {bd}'

Prevention

When it happens

Trigger: Running `python tools/install.py install` (or `make install`) with a --shared configuration but without first building, or with --build-dir pointing somewhere the lib was never written.

Common situations: Forgot to run the build; built into out/Release but installed with default/Debug build_dir; build failed silently; shlib_suffix variable mismatch; the lib landed in an uncovered output dir.

Related errors


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