I believe I’ve identified the issue. This wasn’t a problem before, and I think it should be something within v0 that handles this for everyone who uses Blob storage, rather than having to set up images in a specific way.
Thinking about this, updating all the projects that use v0—around 90 pages across different projects—will take hours and cost a lot of tokens.
While resolving the issue is good news, I’d love to get it working again like it has for months. I’m 12k prompts deep into v0 right now, and today is the first time I’ve encountered this error.
The Root Cause: Next.js Image Optimization Proxy
When you use the Next.js <Image> component without unoptimized, it doesn’t load the image directly from the source URL. Instead, it routes the request through Next.js’s built-in image optimization API at /_next/image?url=...&w=...&q=.... This proxy fetches the original image, resizes/compresses it, converts it to modern formats (like WebP/AVIF), and then serves the optimized version to the browser.
The Problem: URL Encoding with Special Characters
Your Vercel Blob URLs contain complex path segments with encoded characters:
%20 for spaces (e.g., “Placeholder Images” becomes Placeholder%20Images)
%26 for ampersands (e.g., “Services & Conditions” becomes Services%20%26%20Conditions)
When the Next.js image optimizer receives this URL as a query parameter, it needs to double-encode it (since the URL itself becomes a parameter value in /_next/image?url=<encoded-blob-url>). This double-encoding process can mangle the %26 (ampersand) in particular, because the optimizer may interpret it as a query parameter separator (&) rather than a literal part of the path. The result is that the optimizer requests a subtly different (broken) URL from Vercel Blob, gets a 400/404 back, and the image fails to load.
What unoptimized Does
Adding unoptimized tells Next.js: “Skip the optimization proxy entirely. Just put the raw src URL directly into the HTML <img> tag.” The browser then fetches the image straight from Vercel Blob, which handles its own URL encoding perfectly fine. No double-encoding issue, no proxy in the middle - the image loads directly.
Trade-off: You lose automatic resizing/format conversion from Next.js, but since Vercel Blob is already serving compressed .webp files, the practical impact is minimal. The images are already optimized at the source.