# Next.js Image Component Not Rendering: Common Causes and Fixes

> Is your Next.js Image component not rendering? Discover common causes like missing dimensions or unconfigured remote patterns and learn how to fix them with our expert guide.

- Repository: [Vercel/next.js](https://github.com/vercel/next.js)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The Next.js Image component fails silently when required dimensions are missing, remote patterns are unconfigured, or the image is rendered in static export mode without disabling optimization.**

The `<Image />` component in the [`vercel/next.js`](https://github.com/vercel/next.js/blob/main/vercel/next.js) repository is designed to optimize performance by building responsive `srcSet` attributes and handling lazy loading automatically. However, its architecture deliberately suppresses errors in production to prevent page crashes, which often results in blank or zero-size images when configuration is incorrect. Understanding the validation logic inside `getImgProps` and the rendering pipeline in [`image-component.tsx`](https://github.com/vercel/next.js/blob/main/image-component.tsx) is essential for debugging these silent failures.

## Why the Next.js Image Component Fails Silently

The component acts as a thin wrapper that constructs `<img>` attributes on both server and client. When validation fails—such as missing dimensions or disallowed remote hosts—the code in [`packages/next/src/shared/lib/get-img-props.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/shared/lib/get-img-props.ts) forces the image into **unoptimized** mode or strips the `src` attribute entirely to avoid breaking the layout. In development, this triggers clear error messages, but in production builds, the component renders a hidden or empty image element instead of crashing the page.

## Common Reasons Why Images Are Not Rendering

### Missing Width and Height Properties

For non-`fill` images, `getImgProps` validates `widthInt` and `heightInt`. If these integers are missing, the component throws an error in development. In production, it falls back to `unoptimized` mode, which removes the `srcSet` and can result in a blank image if the `src` is also malformed.

Always supply explicit numeric `width` and `height` props, or use the `fill` property for responsive layouts.

### Using Fill Mode Without Relative Positioning

When `fill` is used, the component forces `position: absolute; width: 100%; height: 100%` and checks the parent element's `position` property. If the parent is not `relative`, `absolute`, or `fixed`, the image may be positioned incorrectly or hidden from view.

Wrap `<Image fill ... />` in a container with `position: relative` and explicit dimensions.

### Unconfigured Remote Patterns

The server-side validator in the image optimization API rejects URLs that do not match a configured `remotePatterns` entry. When this happens, `getImgProps` forces the image to `unoptimized`, which can leave the `src` empty if the optimizer endpoint was expected to provide the URL.

Add the remote host to `remotePatterns` in [`next.config.js`](https://github.com/vercel/next.js/blob/main/next.config.js):

```javascript
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.unsplash.com',
      },
    ],
  },
}

```

### Static Export Without Unoptimized Flag

When running `next export`, the built-in optimizer cannot function because it requires a server. `getImgProps` detects `config.output === 'export'` and throws an error unless `images.unoptimized` is explicitly set to `true`.

Disable optimization for static exports:

```javascript
module.exports = {
  images: {
    unoptimized: true,
  },
}

```

### Missing Blur Data URL for Placeholder

Using `placeholder="blur"` requires a `blurDataURL`. In development, `getImgProps` throws a clear error if this is missing. In production, the placeholder remains empty, leaving the image invisible until the real source loads—which may never happen if the source is invalid.

Import the image statically to automatically receive `blurDataURL`, or provide a manually generated data URL.

### Custom Loader Not Implementing Width

When a custom loader is supplied, `getImgProps` checks that the returned URL contains the `width` query parameter. If not, a warning is emitted and the image is treated as unoptimized, resulting in a missing `srcSet` and potential blank render.

Ensure the custom loader returns a URL containing `?w=<width>`:

```javascript
export default function myLoader({ src, width, quality }) {
  return `https://img.example.com/${src}?w=${width}&q=${quality || 75}`
}

```

### SVG Handling Without Dangerously Allow SVG

The default loader treats SVGs as unoptimized. If `dangerouslyAllowSVG` is false (the default), the component may skip the optimization pipeline. When the SVG is served from the internal image-optimizer endpoint without proper configuration, the result can be a blank image.

Enable SVG support in [`next.config.js`](https://github.com/vercel/next.js/blob/main/next.config.js) or serve SVGs as static files:

```javascript
module.exports = {
  images: {
    dangerouslyAllowSVG: true,
    contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
  },
}

```

### Invalid Source Strings

`getImgProps` validates the `src` string and throws an error in development if it contains leading/trailing whitespace or control characters. In production, the URL is silently dropped, resulting in an image with no `src`.

Sanitize the source by trimming whitespace or using `encodeURIComponent` for dynamic paths.

## How the Image Component Processes Props

Understanding the internal pipeline helps diagnose why images disappear. The architecture spans several key files in the [`vercel/next.js`](https://github.com/vercel/next.js/blob/main/vercel/next.js) repository:

1. **Entry Point** – The client-side component lives in [`packages/next/src/client/image-component.tsx`](https://github.com/vercel/next.js/blob/main/packages/next/src/client/image-component.tsx). It receives props and delegates processing to `getImgProps`.

2. **Prop Processing** – [`packages/next/src/shared/lib/get-img-props.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/shared/lib/get-img-props.ts) contains the core validation logic. It merges global configuration from [`packages/next/src/shared/lib/image-config.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/shared/lib/image-config.ts), validates required fields like `widthInt` and `heightInt`, and determines whether the image should be treated as *unoptimized*.

3. **Attribute Generation** – Based on the loader choice (default or custom), the code generates `src`, `srcSet`, and `sizes` attributes. If the loader returns a URL without width parameters, the component falls back to unoptimized mode.

4. **Placeholder Handling** – When `placeholder="blur"` is used, [`packages/next/src/shared/lib/image-blur-svg.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/shared/lib/image-blur-svg.ts) generates a tiny SVG for the blur effect. If `blurDataURL` is missing, the placeholder remains empty.

5. **Server-Side Validation** – The image optimization API in [`packages/next/src/server/og/image-response.ts`](https://github.com/vercel/next.js/blob/main/packages/next/src/server/og/image-response.ts) (and related server files) validates remote URLs against `remotePatterns`. Rejected URLs force the client to treat the image as unoptimized.

If any step in this pipeline fails—whether through missing dimensions, misconfigured loaders, or disallowed remote hosts—the component either throws an error in development or silently renders an empty image element in production.

## Code Examples and Solutions

### Correct Static Import Usage

Static imports automatically provide `width`, `height`, and `blurDataURL`.

```tsx
import Image from 'next/image'
import photo from '@/public/me.jpg'

export default function Avatar() {
  return (
    <Image
      src={photo}
      alt="Me"
      placeholder="blur"
      priority
    />
  )
}

```

### Proper Fill Implementation

Always use a relative positioned parent with explicit dimensions.

```tsx
<div style={{ position: 'relative', width: '100%', height: '300px' }}>
  <Image
    src="/landscape.jpg"
    alt="Landscape"
    fill
    style={{ objectFit: 'cover' }}
  />
</div>

```

### Configuring Remote Patterns

Allow external domains explicitly in your configuration.

```javascript
// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'images.unsplash.com',
      },
    ],
  },
}

```

### Custom Loader Setup

Ensure width parameters are included in the returned URL.

```javascript
// my-image-loader.js
export default function myLoader({ src, width, quality }) {
  return `https://img.example.com/${src}?w=${width}&q=${quality || 75}`
}

```

### Disabling Optimization for Static Export

Required when using `next export` without a server.

```javascript
// next.config.js
module.exports = {
  images: {
    unoptimized: true,
  },
}

```

## Summary

- The Next.js Image component validates props in `getImgProps` and fails silently in production when configuration is invalid, resulting in blank images.
- **Always provide `width` and `height`** (or use `fill` with a relative parent) to prevent the component from falling back to unoptimized mode without a valid `srcSet`.
- **Configure `remotePatterns`** in [`next.config.js`](https://github.com/vercel/next.js/blob/main/next.config.js) for external images; otherwise the optimizer rejects the URL and the image may not render.
- **Set `unoptimized: true`** when using `next export` because the built-in optimizer requires a server environment.
- **Include width parameters in custom loaders** and provide `blurDataURL` when using `placeholder="blur"` to avoid empty placeholders.

## Frequently Asked Questions

### Why is my Next.js image blank even with width and height?

If you are using a remote image, the blank render usually indicates that the domain is not listed in `remotePatterns` in [`next.config.js`](https://github.com/vercel/next.js/blob/main/next.config.js). According to the source code in [`get-img-props.ts`](https://github.com/vercel/next.js/blob/main/get-img-props.ts), when a remote URL fails validation, the component forces `unoptimized` mode, which can strip the `src` if the loader expects an optimized endpoint. Verify your `remotePatterns` configuration and ensure the URL matches the protocol and hostname exactly.

### Does Next.js Image work with static export?

The Image component works with `next export`, but the built-in optimizer does not. As implemented in [`get-img-props.ts`](https://github.com/vercel/next.js/blob/main/get-img-props.ts), the code detects `config.output === 'export'` and throws an error unless you set `images.unoptimized: true` in [`next.config.js`](https://github.com/vercel/next.js/blob/main/next.config.js). With `unoptimized: true`, the component renders a standard `<img>` tag with the original `src` URL, bypassing the optimization API entirely.

### Why does fill mode make my image disappear?

The `fill` property applies `position: absolute` to the image and requires the parent container to establish a positioning context. If the parent lacks `position: relative`, `absolute`, or `fixed`, the image may collapse to zero size or position itself incorrectly in the DOM. The component checks for this in development and emits a warning, but in production the image simply appears blank. Always wrap `fill` images in a container with explicit dimensions and `position: relative`.

### How do I fix remote images not loading in Next.js?

Remote images require explicit permission via the `remotePatterns` configuration in [`next.config.js`](https://github.com/vercel/next.js/blob/main/next.config.js). The validation logic in the image optimization API rejects any URL that does not match a configured pattern, causing the client-side component to receive an empty or unoptimized response. To fix this, add an entry specifying the `protocol` and `hostname` for your image CDN. For example, add `{ protocol: 'https', hostname: 'cdn.example.com' }` to allow images from that domain to be optimized and rendered.