lovell / lovell/sharp

err.code.endsWith() crashes with unhandled TypeError when wasm32 fallback fails (no .code on CompileError)

Open Beginner friendly
#4,592 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug ready-to-ship
Dominant language
JavaScript
Stars
32.7k
Forks
1.4k
Avg merge
1d 14h
Merged PRs (30d)
5

Description

### Is this a possible bug in a feature of sharp, unrelated to installation?

- [x] Running `npm install sharp` completes without error.
- [x] Running `node -e "import 'sharp'"` throws (this is the bug being reported).

### Are you using the latest version of sharp?

- [x] I am using the latest version of `sharp` as reported by `npm view sharp dist-tags.latest` (0.35.3).

### What is the output of running `npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp`?

```
System: Alpine Linux 3.23.3 (linux/amd64), inside Docker on a Proxmox VM
Node: v24.13.0
npmPackages: sharp: 0.35.3
```

### What are the steps to reproduce?

On a CPU that doesn't support the x86-64-v2 microarchitecture (in my case a Proxmox VM with a generic `kvm64`-class CPU type, missing `ssse3`/`sse4_1`/`sse4_2`/`popcnt`), importing sharp crashes the whole process with an unrelated `TypeError` instead of a clear error message.

1. `require("@img/sharp-linuxmusl-x64/sharp.node")` loads the native binding fine.
2. `sharp._isUsingX64V2()` correctly returns `false` on this CPU.
3. sharp discards the native binding, pushes an error with `code: "Unsupported CPU"`, and falls back to the wasm32 build.
4. `require("@img/sharp-wasm32/sharp.node")` throws:
```
CompileError: WebAssembly.Module(): Wasm SIMD unsupported @+2188
```
This error has **no `.code` property** (`typeof err.code === "undefined"`).
5. That error is pushed into the same `errors` array as the others.
6. This code in `sharp.mjs` then runs:
```js
errors.forEach((err) => {
if (!err.code.endsWith("MODULE_NOT_FOUND")) {
```
Since the wasm32 `CompileError` has `err.code === undefined`, `.endsWith()` throws:
```
TypeError: Cannot read properties of undefined (reading 'endsWith')
at file:///.../node_modules/sharp/dist/sharp.mjs:115:19
```
This crashes the whole process instead of surfacing the real, actionable message (that the CPU lacks required instructions and no fallback is available).

I confirmed this isn't a detection bug: `_isUsingX64V2()` is correctly reporting an unsupported CPU here, once I fixed the underlying CPU config the whole thing worked as expected. So the ask isn't about the microarchitecture check itself, just the crash that happens afterward.

### Minimal reproduction of each step

```bash
node -e "require('@img/sharp-linuxmusl-x64/sharp.node')"
# -> loads fine

node -e "const s=require('@img/sharp-linuxmusl-x64/sharp.node'); console.log(s._isUsingX64V2())"
# -> false

node -e "try{require('@img/sharp-wasm32/sharp.node')}catch(e){console.log(e); console.log(typeof e.code)}"
# -> CompileError: WebAssembly.Module(): Wasm SIMD unsupported @+2188
# -> undefined
```

### What is the expected behaviour?

`sharp.mjs` line 115 assumes every error pushed into the `errors` array has a string `.code`, which isn't guaranteed, a `CompileError` from a failed wasm instantiation has none. A defensive check like `String(err.code || '').endsWith(...)` would let the real underlying message reach the user (e.g. "CPU doesn't support x86-64-v2 and wasm32 fallback isn't usable either") instead of an unrelated `TypeError` that just says "endsWith of undefined".

This will affect anyone running sharp 0.35.x on a CPU without x86-64-v2 support and no working wasm/SIMD fallback, which is a fairly common situation in VMs with a generic/capped CPU type (e.g. Proxmox's older default CPU model).

### Environment

- Alpine Linux 3.23.3
- Node.js v24.13.0
- sharp 0.35.3
- linux/amd64, inside Docker, no cross-arch/emulation
- CPU exposed to the VM was missing ssse3/sse4_1/sse4_2/popcnt (fixed on my end by changing the VM's CPU type in Proxmox, unrelated to this bug report but explains why it triggered)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at sharp.mjs line 115 and reproduce the fallback path with the wasm32 binding commands shown in the issue. Check how errors from the native and wasm bindings are collected and filtered. Done means a wasm CompileError without a code property reaches the user as the underlying actionable error rather than causing an unrelated TypeError.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs, wasm
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.