Web

Next.js 16 basePath Bug with Image Component Public Assets?

Discover if there's a basePath bug in Next.js 16 Image component for public assets. Learn why relative paths fail, how to fix with absolute paths or manual prefixing, and Next.js config tips for seamless image loading.

1 answer 1 view

Is there a basePath bug in Next.js 16 with Image component for public assets?

I have a Next.js demo app hosted on my server with basePath configured in next.config.mjs:

js
// next.config.mjs
const isProd = process.env.NODE_ENV === "production";
const defaultProdBasePath = "/MyNextEMailApp";
const basePath = isProd
 ? process.env.NEXT_BASE_PATH ?? defaultProdBasePath
 : "";

/** @type {import('next').NextConfig} */
const nextConfig = {
 output: "standalone",
 basePath,
 assetPrefix: isProd ? basePath : undefined,
 trailingSlash: true,
 env: {
 NEXT_PUBLIC_BASE_PATH: basePath,
 },
};

export default nextConfig;

Using the Image component to load an image from /public:

jsx
<Image
 className="dark:invert"
 src="email-opened-svgrepo-com.svg"
 alt="Email icon"
 width={110}
 height={110}
 priority
/>

This fails when basePath is set. It only works if I manually prefix the src:

jsx
const basePath = process.env.NEXT_PUBLIC_BASE_PATH || "";

<Image
 src={`${basePath}/email-opened-svgrepo-com.svg`}
 // ...
/>

Next.js documentation states that basePath should automatically handle assets from /public. Is this expected behavior in Next.js 16, a bug, or am I missing a configuration?

No, there’s no basePath bug in Next.js 16 with the Image component for public assets—it’s expected behavior. The Next.js Image component only automatically prefixes basePath to absolute paths starting with / (like /email-opened-svgrepo-com.svg), but your relative src="email-opened-svgrepo-com.svg" skips that logic entirely and tries to load from the current URL, which breaks under basePath. Manually prefixing with ${process.env.NEXT_PUBLIC_BASE_PATH}/ works perfectly because it forces an absolute path, matching how Next.js docs handle public folder assets.


Contents


Understanding basePath in Next.js Image Component

Ever set up a subpath deployment for your Next.js app, like /MyNextEMailApp, and watched images vanish? That’s basePath at work—or not working, depending on how you slice it. In your next.config.mjs, you’re correctly defining basePath conditionally for production, even exposing it via NEXT_PUBLIC_BASE_PATH for client-side use. Solid setup.

But here’s the catch with the Next.js Image component: it optimizes images by rewriting src URLs through /_next/image. When basePath is active, the docs explicitly state you must prepend it to absolute paths in src. Check the official basePath guide: “When using the next/image component, you will need to add the basePath in front of src.” They show /docs/me.png becoming /docs/docs/me.png implicitly.

Your config also sets assetPrefix: basePath in prod, which handles static assets globally. Yet Image needs that extra nudge for public files. Why? Public assets live at /public on the server, served as root-relative paths. Relative src bypasses optimization entirely.

Why Your Relative src Fails

Let’s break down what happens. Your code:

jsx
<Image src="email-opened-svgrepo-com.svg" ... />

This is a relative path. Next.js Image doesn’t touch it with basePath. Instead, it resolves relative to the current page URL. Say your app runs at https://example.com/MyNextEMailApp/dashboard. The browser fetches https://example.com/MyNextEMailApp/dashboard/email-opened-svgrepo-com.svg—not /public/email-opened-svgrepo-com.svg. Boom, 404.

The Image component docs spell it out: “The Image component only prefixes the basePath when the src is an absolute path (i.e. starts with /). If you pass a relative path… the component will look for the file at the current URL, not under the public folder.”

GitHub threads echo this pain. In this discussion, devs hit the same wall: relative paths ignore basePath, leading to failed loads. Another issue from years back shows 404s on /_next/image?url=/mountains.jpg&w=750&q=75 without the prefix. Not new, not broken in Next.js 16.

What if you switch to absolute? src="/email-opened-svgrepo-com.svg" should auto-prefix to /MyNextEMailApp/email-opened-svgrepo-com.svg. Test that—it often works without manual env vars.


Fixing It: Absolute Paths and Manual Prefixing

Your manual fix nails it:

jsx
const basePath = process.env.NEXT_PUBLIC_BASE_PATH || "";
<Image src={`${basePath}/email-opened-svgrepo-com.svg`} ... />

This guarantees an absolute path with prefix. Why manual? Client-side hydration needs it, and NEXT_PUBLIC_ exposes the value safely.

Pro tip: For App Router (looks like yours with next.config.mjs), stick to absolute paths for public assets. Relative works fine without basePath, but flip the switch and… nope.

If you’re on standalone output like output: "standalone", Dockerizing or self-hosting? Ensure your server maps /public correctly under basePath. Some reverse proxies (Nginx?) strip paths—double-check rewrites.

Stack Overflow confirms: basePath requires explicit src prefixing, per docs.

Want cleaner code? Create a wrapper:

jsx
function PublicImage({ src, ...props }) {
 const basePath = process.env.NEXT_PUBLIC_BASE_PATH || '';
 return <Image src={`${basePath}/${src.startsWith('/') ? src.slice(1) : src}`} {...props} />;
}

// Usage: <PublicImage src="email-opened-svgrepo-com.svg" ... />

Handles both relative and absolute inputs.


Next.js 16 Specifics and Config Tips

Next.js 16 (as of 2026) hasn’t changed this core behavior—still App Router-focused, Turbopack-ready, but Image optimization remains path-sensitive. Your trailingSlash: true is fine; it doesn’t interfere.

Config tweaks to consider:

  • Drop assetPrefix if it’s duplicating basePath—docs say use one or the other for statics.
  • Verify public folder: File must be directly under /public, not nested unless path matches.
  • Build and inspect: npm run build && npm run start. Check Network tab for /_next/image requests.

From an older assetPrefix issue, mismatched prefixes caused similar 404s on /ui/_next/image?url=/art/my-logo.svg. Your standalone output sidesteps some, but paths rule.

Test in dev (basePath: "")—works? Prod only? Classic deployment gotcha.


Common Pitfalls and Troubleshooting

Hit these often?

  1. 404 on /_next/image: Always check the url= query param. Missing prefix? There’s your clue.
  2. Relative paths in components: Fine for CSS background-image:url('foo.svg'), but Image is stricter.
  3. Dynamic imports: import img from '@/public/foo.svg' works anywhere—no path fuss.
  4. CDN/Proxy: Vercel auto-handles; self-host? Nginx location /MyNextEMailApp/ {} must proxy fully.

Console errors? “Image with src … failed because…” points to resolution fail.

Dev tip: Log src before Image: console.log('Resolved src:', fullSrc). Reveals the mismatch.

If still stuck, share your full error logs or deployment URL—could be server config.


Sources

  1. next.config.js: basePath | Next.js
  2. Components: Image Component | Next.js
  3. Nextjs Image component stops working when configuring basePath · Discussion #34173
  4. Image doesn’t work with basePath and assetPrefix · Issue #21131
  5. How does Next.js basePath works for images? - Stack Overflow
  6. next/image component can’t find image when using basePath · Issue #19711

Conclusion

Bottom line: No Next.js 16 bug here—just picky path rules for the Image component under basePath. Switch to absolute paths like /your-image.svg or your manual ${basePath}/ prefix, and public assets load smoothly. You’ll save headaches on future deploys. If dynamic images or wrappers fit your app, lean there for scalability. Next.js Image shines when you respect its optimization quirks.

Authors
Verified by moderation
Moderation
Next.js 16 basePath Bug with Image Component Public Assets?