parcel-bundler/parcel · critical · Error

Failed to load native binding

Error message

Failed to load native binding

What it means

Thrown by @parcel/rust's binding loader after the platform/arch switch when nativeBinding is still falsy AND no loadError was captured. It indicates the loader never assigned a binding (a logic/coverage gap) rather than a require() failure, which would have surfaced via loadError instead.

Source

Thrown at packages/core/rust/index.js:323

            nativeBinding = require('@parcel/rust-linux-s390x-gnu');
          }
        } catch (e) {
          loadError = e;
        }
        break;
      default:
        throw new Error(`Unsupported architecture on Linux: ${arch}`);
    }
    break;
  default:
    throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`);
}

if (!nativeBinding) {
  if (loadError) {
    throw loadError;
  }
  throw new Error(`Failed to load native binding`);
}

const {
  findAncestorFile,
  findFirstFile,
  findNodeModule,
  hashString,
  hashBuffer,
  Hash,
  optimizeImage,
  transformHtml,
  packageHtml,
  optimizeHtml,
  transformSvg,
  packageSvg,
  optimizeSvg,
  svgReact,
  Resolver,

View on GitHub (pinned to 59484858a1)

Solutions

  1. Reinstall dependencies with optional deps enabled: `npm ci` (do not pass --no-optional).
  2. Verify the local prebuilt .node file or the @parcel/rust-<platform-arch> package is present in node_modules.
  3. Clear npm cache and node_modules (`rm -rf node_modules package-lock.json && npm i`).
  4. If persistent, file an upstream issue — this code path implies a loader bug worth reporting with platform/arch details.

Example fix

# before
$ npm install --no-optional   # prebuilt skipped -> nativeBinding never set

# after
$ npm ci   # optionalDependencies install the platform binding
Defensive patterns

Strategy: validation

Validate before calling

// After install, assert the platform binding is present before importing @parcel/rust.
const { platform, arch } = require('process');
const fs = require('fs');
const path = require('path');
const bindingDir = path.dirname(require.resolve('@parcel/rust/package.json'));
const hasBinding = fs.readdirSync(bindingDir)
  .some(f => f.includes(`${platform}-${arch}`));
if (!hasBinding) {
  throw new Error('No native binding installed; run `npm ci` without --no-optional.');
}

Prevention

When it happens

Trigger: Control flow reaches the post-switch guard with nativeBinding unset because a case branch returned early without assigning and without throwing — e.g. a missing break assignment path, or a future platform case added without populating nativeBinding.

Common situations: Seen after partial installs where the correct @parcel/rust-<platform-arch> optional dependency was skipped (npm --no-optional) but the local .node file also absent; or a packaging bug where the case exists but both localFileExisted and the package require were bypassed.

Related errors


AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13). Data as JSON: /api/errors/94a9731e3aff8a4d. Report an issue: GitHub.