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-clidirectly, wasm-pack, Trunk or a framework’s build tool. - [ ] Access to
Cargo.lockand 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.
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.
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-bindgenbut notjs-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.
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.
Related
- Building Rust Wasm without wasm-pack — running the CLI yourself.
- Caching Rust Wasm builds in GitHub Actions — caching the CLI correctly.
- Migrating from old wasm-bindgen versions — upgrading across changes.
- Reading the glue code wasm-bindgen generates — what the CLI produces.
← Back to Troubleshooting Common Wasm Errors