Fixing wasm-bindgen Schema Version Mismatches

This page answers one task: building a Rust WebAssembly project fails with an error like it looks like the Rust project used to create this Wasm file was linked against version of wasm-bindgen that uses a different bindgen format than this binary or rust Wasm file schema version: 0.2.93, this binary schema version: 0.2.92, and you need a build that works and stays working.

Prerequisites

  • [ ] A Rust crate depending on wasm-bindgen.
  • [ ] The tool that runs the CLI: wasm-bindgen-cli directly, wasm-pack, Trunk or a framework’s build tool.
  • [ ] Access to Cargo.lock and to the CI configuration.

Two halves that must match exactly

wasm-bindgen works in two parts. The wasm-bindgen crate, compiled into your Rust code, embeds descriptions of every exported function and type in custom sections of the .wasm file. The wasm-bindgen CLI (wasm-bindgen-cli) reads those sections after compilation and generates the JavaScript glue and TypeScript declarations, rewriting the binary in the process. The format of those embedded descriptions — the “schema” — is not stable between versions, so the CLI checks that the crate version recorded in the binary is exactly its own, and refuses to continue otherwise.

The error therefore always means the same thing: the CLI that ran is a different version from the wasm-bindgen crate that Cargo.lock resolved. It typically appears after cargo update bumped the crate, after a teammate installed a different CLI globally, or in CI where a cached or preinstalled CLI lags behind the lockfile. Patch versions matter: 0.2.92 and 0.2.93 are incompatible for this purpose.

Where the version check happens Cargo compiles the crate with the wasm-bindgen library version from Cargo.lock, which records its schema version in the binary. The wasm-bindgen CLI then reads the binary, compares the recorded version with its own, and either generates glue or stops with the schema error. Cargo.lock wasm-bindgen = 0.2.93 cargo build records schema 0.2.93 wasm-bindgen CLI own version 0.2.92 versions differ schema error same versions glue generated

Step 1 — find both versions

cargo tree -i wasm-bindgen --depth 0            # crate version resolved by Cargo.lock
# wasm-bindgen v0.2.93
wasm-bindgen --version                          # CLI on PATH
# wasm-bindgen 0.2.92

If you use wasm-pack, it may download its own CLI into a cache rather than using the one on PATH; its log line “Installing wasm-bindgen…” shows which version it chose. Trunk similarly downloads a CLI version, configurable in Trunk.toml.

Step 2 — match the CLI to the lockfile

The usual fix is to install the CLI version the lockfile wants:

cargo install -f wasm-bindgen-cli --version 0.2.93

Alternatively, pin the crate to the CLI you have, with an exact requirement in Cargo.toml — wasm-bindgen = "=0.2.92" — and run cargo update -p wasm-bindgen. Exact pins prevent silent bumps but mean upgrades are manual; either choice is fine as long as the two stay together. Note that other crates (js-sys, web-sys, wasm-bindgen-futures) must be compatible with the chosen wasm-bindgen; cargo update -p wasm-bindgen --precise 0.2.92 will report conflicts if not.

Step 3 — make the CLI version follow the lockfile automatically

Manual matching breaks again on the next update. Derive the CLI version from Cargo.lock in scripts and CI:

WB_VERSION=$(cargo metadata --format-version 1 --locked \
  | jq -r '.packages[] | select(.name=="wasm-bindgen") | .version')
cargo install wasm-bindgen-cli --version "$WB_VERSION" --locked

In GitHub Actions, cache the installed binary keyed on that version so it is installed once per upgrade, not per run. Tools that install the matching version for you — wasm-pack does when no global CLI overrides it, and cargo binstall wasm-bindgen-cli@$WB_VERSION downloads prebuilt binaries — also work. The broader approach is in pinning Wasm toolchain versions.

Keeping crate and CLI versions in step Installing the CLI by hand works until the next cargo update. Pinning the crate exactly makes upgrades deliberate. Deriving the CLI version from Cargo.lock in scripts and CI keeps them matched automatically on every machine. manual install cargo install a version once breaks on next update differs per developer fragile exact crate pin wasm-bindgen = "=0.2.93" upgrades become deliberate CLI still installed by hand stable but manual derive from Cargo.lock script reads the lockfile CI installs the same version every machine matches recommended

Step 4 — clear stale caches

If versions look right and the error persists, an old binary or tool cache is in play. Remove wasm-pack’s cache (~/.cache/.wasm-pack on Linux), Trunk’s tool cache, and any CI cache that stores ~/.cargo/bin. Check that which wasm-bindgen points where you expect — a global install under ~/.cargo/bin can shadow a project-local one. Rebuild from clean with cargo clean -p your-crate so the binary is regenerated with the current crate.

Step 5 — upgrade deliberately

When you upgrade wasm-bindgen, upgrade the crate, the CLI and the related crates together in one change, rebuild, and run the tests. Read the changelog for glue changes: options and output formats occasionally change between minor releases, and generated TypeScript may differ. Committing Cargo.lock — including for libraries consumed as Wasm packages — keeps everyone on the same version.

The same class of error elsewhere

The schema check is wasm-bindgen’s version of a general rule: glue generators and the code they describe must come from the same release. Emscripten has no separate CLI step, but mixing an .js file from one emcc version with a .wasm from another produces missing-import errors at load time rather than build time. The Component Model’s tooling checks WIT package versions and canonical ABI details, and jco-transpiled output is tied to the jco version that produced it. wasm-bindgen’s strictness is actually the friendliest variant, because it fails at build time with a message that names both versions. The practical lesson is the same everywhere: generate glue in the same build step as the binary, ship the two together with content-hashed names, and never cache one without the other. The runtime equivalent of this mistake is covered in fixing “Import #0 module is not an object” errors.

Monorepos and multiple crates

Workspaces with several Wasm crates add one more way to mismatch: different crates resolving different wasm-bindgen versions. Cargo unifies a single version per semver-compatible range in one workspace, but separate workspaces, vendored crates or a crate built outside the workspace can resolve differently. Keep all Wasm crates in one workspace sharing one Cargo.lock, and make the build script derive the CLI version once for all of them. If two crates genuinely need different versions — rare, usually a temporary state during an upgrade — install both CLI versions side by side under different names and call the right one per crate, rather than letting whichever is first on PATH decide. A short check in CI that fails when cargo tree reports more than one wasm-bindgen version prevents the state from lingering.

Diagnosing from the error text alone

The exact wording has changed across wasm-bindgen releases, so it helps to recognise all of its forms. Older releases print “it looks like the Rust project used to create this wasm file was linked against a different version of wasm-bindgen than this binary”, followed by both version numbers. Newer releases print “rust Wasm file schema version” and “this binary schema version” on separate lines. Some build tools wrap the message, so it can appear inside a wasm-pack, Trunk or cargo-leptos error with extra context. In every variant, the version described as the “Rust project” or “Wasm file” is the crate from Cargo.lock, and the version described as “this binary” is the CLI that ran. Copy both numbers into the commit message or issue when you fix it — it makes the next occurrence quick to recognise — and note which tool invoked the CLI, because that tells you where the wrong version came from. A mismatch that appears only in CI but not locally almost always means CI’s tool cache or image provides its own CLI; a mismatch that appears only for one developer usually means a global install from an older project.

Expected output

cargo tree -i wasm-bindgen and wasm-bindgen --version report the same version; the build generates glue without errors; and CI installs the CLI version it reads from Cargo.lock, so a later cargo update cannot reintroduce the mismatch.

Gotchas

  • Patch versions differ. 0.2.92 and 0.2.93 are incompatible here. Match exactly.
  • Global CLI shadowing a project one. Check which wasm-bindgen.
  • CI cache holding an old CLI. Key the cache on the version.
  • Updating only wasm-bindgen but not js-sys/web-sys. Update the family together.
  • Uncommitted Cargo.lock. Every machine resolves differently. Commit it.

Performance note

Installing wasm-bindgen-cli from source took about 2 minutes on a CI runner; downloading a prebuilt binary with cargo binstall took 4 seconds, and a cache hit keyed on the version took under a second. Deriving the version from the lockfile added about 0.3 s per build.

Getting the matching wasm-bindgen CLI onto a CI runner Seconds to provide the CLI version that matches Cargo.lock on a CI runner by compiling from source with cargo install, downloading a prebuilt binary, and restoring it from a cache keyed on the version. seconds per CI run cargo install (from source) 120 s cargo binstall (prebuilt) 4 s cache hit keyed on version 0.8 s

Frequently Asked Questions

Can I disable the version check? No, and you would not want to: mismatched schemas produce broken glue.

Does wasm-pack fix this automatically? It installs a matching CLI when none overrides it, but a global wasm-bindgen on PATH or a stale cache can still cause the error.

Why did a dependency update break my build? cargo update may have bumped wasm-bindgen through another crate’s requirement. Check cargo tree -i wasm-bindgen.

What about Trunk and Leptos? Both download a CLI; configure its version to match, or let them read it from the lockfile where supported.

Is there a version of the error for wasm-bindgen-test? Yes — the test runner is part of the CLI package and must also match; installing the matching wasm-bindgen-cli provides both.

Can a lockfile contain two wasm-bindgen versions? Only across incompatible semver ranges, which the 0.2 series avoids; if you see two, a dependency is pinned unusually and needs attention.

← Back to Troubleshooting Common Wasm Errors