---
title: "Invalid src prop… hostname is not configured: It's One File, Not Two"
published: true
description: "The next/image \"hostname is not configured\" error means your remote host isn't in remotePatterns — not your CSP. Here's the real one-file fix and why."
tags: nextjs, webdev, debugging, react
canonical_url: https://brokeinprod.dev/debugging/next-image-hostname-not-configured
---
The upload worked! The database had the real URL. The page still crashed —
because the part of Next.js that renders images had never heard of the host
the part that stores them had just used.Start here: Add the image host to
images.remotePatternsinnext.config.ts(protocol, hostname, port, pathname), then restart the dev server — the config is read once, at startup. You do not need to touch your CSP — optimizednext/imagerequests are served same-origin from/_next/image, soimg-src 'self'already covers them. CSP only enters the picture if you bypass the optimizer (see below).
The setup
I was building the admin side of a portfolio site for an artist — a small CRUD panel where the website owner uploads artwork and video thumbnails instead of editing code. Uploads go to object storage (Vercel Blob), the public URL gets saved in Postgres, and the front end renders everything through Next.js's <Image> component for automatic resizing and WebP conversion.
The upload itself worked on the first try. The file landed in storage, the URL came back, and the row saved. Then the page tried to render the image and the whole thing threw a runtime error.
The symptom
Invalid src prop (https://<your-store>.public.blob.vercel-storage.com/artwork/file.webp)
on `next/image`, hostname "<your-store>.public.blob.vercel-storage.com"
is not configured under images in your `next.config.js`
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
The important thing to notice: the upload didn't fail. Storage was fine, the database was fine — you can open the URL in a browser tab and the file is right there. This is next/image refusing to render a remote host it hasn't been told to trust: a hard runtime error, on purpose, not a broken-image icon. The error even hands you the docs link — which is genuinely the fastest path to the fix.
The diagnosis
next/image isn't an <img> tag; it's a front door to Next's Image Optimization API. By default, every image runs through the optimizer, which fetches the source server-side, resizes it, converts it to a modern format, and produces the result from your own domain. Because the optimizer makes a server-side request to whatever host you give it, an open src would be an abuse vector — an optimizer that fetches arbitrary URLs is a free proxy wearing your domain name. So Next.js requires an explicit allowlist: images.remotePatterns.
If the host of your src isn't in that list, you get the error above — before a single byte is fetched. The error is the security model working. Your job is to tell it, precisely, which hosts are yours.
One detail that catches a lot of people off guard: the match is exact and case-sensitive across every part of the URL — protocol, hostname, port, and pathname. https is not http. assets.example.com is not example.com. A too-shallow pathname (/images/ vs /images/**) fails just as hard. So if you've added the host and it still errors, you almost certainly have a part mismatch, not a missing entry.
And if a tutorial shows images.domains instead: that's the old way — deprecated since Next.js 14 in favor of remotePatterns (which can scope protocol, port, and path, where domains can't), and Next.js 16 lists it for removal in a future major version. Still works today with a warning; don't write new config with it.
The fix
Add the host to remotePatterns in next.config.ts:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "<your-store>.public.blob.vercel-storage.com",
port: "",
pathname: "/**",
},
],
},
};
export default nextConfig;
On recent Next.js versions there's a terser shorthand that takes a URL directly:
images: {
remotePatterns: [new URL("https://<your-store>.public.blob.vercel-storage.com/**")],
}
Then restart the dev server — next.config is read once at startup and isn't hot-reloaded, so without a restart you'll swear the fix didn't work. Editing the config and watching the same error is the classic second act of this bug.
# stop the dev server, then:
npm run dev
Scope the pattern to your store, not the platform
A word on wildcards, because a pattern you'll see in a lot of posts is subtly wrong:
hostname: "*.public.blob.vercel-storage.com" // don't do this
That looks account-scoped. It isn't — it matches every Vercel Blob store on the platform, including anyone else's. If someone can get a URL into your pages, your optimizer will happily fetch and serve images from a stranger's store under your domain. And the fully open hostname: "**" is worse still: it makes the error vanish and reopens the exact open-proxy problem the allowlist exists to close. Scope the pattern to the narrowest true thing — your exact store hostname and a path prefix.
One more thing about that error message: it was doing me a favor. An image
optimizer that fetches from any URL on the internet is a free proxy wearing
your domain name. The allow-list that interrupted my afternoon is the only
thing standing between "renders my images" and "renders anyone's."
The CSP twist (the part most posts get wrong)
If you run a strict Content-Security-Policy, you might expect to also add the Blob host to your img-src directive — some posts even frame this error as a "two files" fix. You usually don't have to — and here's the reasoning, because it's worth understanding rather than copy-pasting.
When optimization is on (the default), the browser never requests the Blob URL directly. It requests /_next/image?url=... from your own origin, and Next.js fetches the remote source server-side. So as far as the browser's CSP is concerned, the image is same-origin and img-src 'self' already allows it. That's why this site's CSP never listed the Blob host, yet the images rendered.
You only need the remote host in img-src when you've taken the image out of the optimizer's path:
- you set
unoptimizedon the image or globally, - you use a custom loader that returns the remote URL,
- you render it with a plain
<img>tag or a CSSbackground-image, - or you reference it in an Open Graph /
<meta>tag (those aren'tnext/imageat all).
So the honest rule is: remotePatterns is the fix; CSP is a conditional follow-up that only applies if you bypass optimization. The two allowlists answer different questions — remotePatterns is Next's permission to fetch and optimize the image; img-src is the browser's permission to display whatever URL actually ends up in the page. With the default loader, that URL is your own origin, so the browser's question is already answered.
What I'd do differently
Set up remotePatterns the moment you wire in object storage, before the first upload — not after the first crash. It's two minutes of config that turns a confusing runtime error into a non-event. And scope the pattern to the exact host and path prefix you control; the wildcard is a smell, not a shortcut.
FAQ
The upload worked but the image won't render — why?
Different systems. Storage happily accepts and serves the file; next/image separately refuses to optimize from hosts you haven't allowlisted. A reachable URL proves nothing about the allowlist. Fixing remotePatterns doesn't touch the upload at all.
I added the pattern and it still fails. Why?
In order of likelihood: you didn't restart the dev server; or the pattern mismatches in one strict part (protocol, subdomain, port, pathname depth). If it works locally but fails in production and you've bypassed optimization (unoptimized, custom loader, plain <img>), then — and only then — check your CSP's img-src.
Can I just set unoptimized and skip this?
You can — per-image or globally — and you give up resizing, format conversion, and blur placeholders. It's an escape hatch for special cases (SVGs, tiny icons), not the fix for an unconfigured host. Note that unoptimized also puts the remote URL back in the browser's path, so a strict CSP would then need the host in img-src.
Do local images need remotePatterns?
No. remotePatterns only governs remote hosts. Images you import or serve from /public are local and exempt.
Further reading
-
Next.js —
next/imageUn-configured Host (the page the error links to; explains exact-match rules and thenew URL()shorthand): https://nextjs.org/docs/messages/next-image-unconfigured-host -
Next.js — Image component API reference (
remotePatterns, thedomainsdeprecation, loaders, the/_next/imageoptimization path): https://nextjs.org/docs/app/api-reference/components/image - Next.js — Image Optimization guide (how the default loader fetches remote images and serves them from your own server): https://nextjs.org/docs/app/getting-started/images
{/* AFFILIATE (internal): Bunny.net optional closing aside when machinery fires up.
Cross-links at publish of the targets: → P-02 (why object storage),
→ P-03 (the CSP companion — 'self' covering /_next/image explained in full),
→ P-06 (cache/restart). SEO title variant for seoTitle field if the site adds
one: "Fix next/image 'hostname is not configured' in Next.js" */}
Top comments (0)