Diagnosing the /_next/image Issue π
Based on your setup, this is almost certainly a silent sharp fallback β Next.js canβt use sharp, so it falls back to passing the original image through unoptimized. Hereβs the full breakdown:
Root Cause: No working sharp = no optimization
Next.js image optimization requires sharp at runtime in standalone mode. When sharp fails to load (for any reason), Next.js does not throw an error β it silently serves the original image as-is. Thatβs exactly what youβre seeing: same file size, correct content-type, but no actual optimization.
Youβve already identified both sharp failure modes:
| Mode |
Your Error |
sharp (native) |
Requires SSE4.2 / x64-v2 CPU β your host CPU is older |
@img/sharp-wasm32 |
Wasm SIMD unsupported in your Node/V8 environment |
Why NEXT_SHARP_PATH Isnβt Enough
Setting NEXT_SHARP_PATH tells Next.js where to find sharp, but if the binary at that path canβt actually execute (CPU mismatch, Wasm SIMD missing), the import fails silently and optimization is skipped. The env var doesnβt fix the underlying incompatibility.
Fix Options (in order of preference)
Option 1: Force a compatible sharp build (recommended)
The native SSE4.2 requirement comes from the prebuilt binary. You can force a build from source inside your Docker image, which compiles for your specific CPU:
FROM node:24 AS base
Install build deps for compiling sharp from source
RUN apt-get update && apt-get install -y
python3 make g++ libvips-dev
&& rm -rf /var/lib/apt/lists/*
Force sharp to compile from source instead of using prebuilt
ENV SHARP_IGNORE_GLOBAL_LIBVIPS=1
ENV npm_config_sharp_binary_host=""
After your npm/pnpm install:
RUN npm rebuild sharp --build-from-source
or: pnpm rebuild sharp --build-from-source
This compiles sharp against the actual CPU in your Docker host rather than relying on a prebuilt binary that assumes SSE4.2.
Option 2: Pin to a sharp version with a broader prebuilt
sharp 0.32.x prebuilts had slightly broader CPU compatibility. Worth trying before going full compile-from-source:
npm install sharp@0.32.6
Option 3: Use a Wasm build with SIMD disabled
If Wasm SIMD is the blocker, you can try forcing the non-SIMD Wasm path:
ENV NEXT_SHARP_PATH=/app/node_modules/@img/sharp-wasm32
And install it explicitly:
npm install @img/sharp-wasm32
Note: this is significantly slower than native but will optimize images correctly.
Option 4: Verify sharp actually loads at startup
Add this to your next.config.ts temporarily to confirm whether sharp is loading:
// At the top of next.config.ts
try {
const sharp = require('sharp');
console.log('β
sharp loaded:', sharp.versions);
} catch (e) {
console.error('β sharp failed to load:', e.message);
}
Check your Docker container logs on startup β if you see the β, that confirms the silent fallback.
Option 5: Custom /api/image route (your fallback plan)
If none of the above work due to infrastructure constraints, a custom route using sharp directly gives you full control:
// app/api/image/route.ts
import sharp from 'sharp';
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const src = searchParams.get('src')!;
const w = Number(searchParams.get('w') ?? 1200);
const q = Number(searchParams.get('q') ?? 75);
const res = await fetch(src);
const buffer = Buffer.from(await res.arrayBuffer());
const optimized = await sharp(buffer)
.resize(w)
.webp({ quality: q })
.toBuffer();
return new Response(optimized, {
headers: {
'Content-Type': 'image/webp',
'Cache-Control': 'public, max-age=604800, immutable',
},
});
}