What Causes This Error?
This error occurs when you try to use a local image with a string path instead of importing it. Astro requires local images to be imported so it can optimize them at build time.
The Problem
---
import { Image } from 'astro:assets';
---
<!-- ❌ String path for local image -->
<Image src="../assets/photo.jpg" alt="Photo" />
<Image src="./images/hero.jpg" alt="Hero" />
The Fix
Import the Image
---
import { Image } from 'astro:assets';
// ✅ Import the image
import photo from '../assets/photo.jpg';
import hero from './images/hero.jpg';
---
<Image src={photo} alt="Photo" />
<Image src={hero} alt="Hero" />
Common Scenarios
Multiple Images
---
import { Image } from 'astro:assets';
import image1 from '../assets/image1.jpg';
import image2 from '../assets/image2.jpg';
import image3 from '../assets/image3.jpg';
---
<Image src={image1} alt="Image 1" />
<Image src={image2} alt="Image 2" />
<Image src={image3} alt="Image 3" />
Dynamic Imports with Glob
---
import { Image } from 'astro:assets';
// ✅ Use import.meta.glob for dynamic paths
const images = import.meta.glob<{ default: ImageMetadata }>(
'../assets/gallery/*.{jpg,png,webp}',
{ eager: true }
);
const gallery = Object.values(images).map((mod) => mod.default);
---
{gallery.map((image, index) => (
<Image src={image} alt={`Gallery image ${index + 1}`} />
))}
Content Collections
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: ({ image }) => z.object({
title: z.string(),
// ✅ Use image() helper for local images
coverImage: image(),
}),
});
---
title: My Post
coverImage: ./cover.jpg
---
---
import { Image } from 'astro:assets';
const { post } = Astro.props;
---
<!-- ✅ Content collection images are pre-imported -->
<Image src={post.data.coverImage} alt={post.data.title} />
Public Directory Images
---
// Images in public/ can use string paths
// But they won't be optimized
---
<!-- ✅ Public images use / prefix -->
<img src="/images/logo.png" alt="Logo" />
<!-- For optimization, import from src/assets instead -->
Conditional Images
---
import { Image } from 'astro:assets';
import defaultImage from '../assets/default.jpg';
// ✅ Import all possible images
import heroLight from '../assets/hero-light.jpg';
import heroDark from '../assets/hero-dark.jpg';
const isDark = true;
const heroImage = isDark ? heroDark : heroLight;
---
<Image src={heroImage} alt="Hero" />
Props with Images
---
// Card.astro
import { Image } from 'astro:assets';
import type { ImageMetadata } from 'astro';
interface Props {
image: ImageMetadata;
title: string;
}
const { image, title } = Astro.props;
---
<div class="card">
<Image src={image} alt={title} />
<h2>{title}</h2>
</div>
---
// Usage
import Card from './Card.astro';
import productImage from '../assets/product.jpg';
---
<Card image={productImage} title="Product Name" />
Why Imports Are Required
✅ Imported images:
- Get optimized (resized, compressed)
- Get content hashes for caching
- Are validated at build time
- Work with Image component features
❌ String paths:
- Skip optimization
- No build-time validation
- Miss out on automatic formats
- Can break in production
Quick Checklist
- Use
importstatements for local images - Use
import.meta.globfor dynamic images - Content collections use
image()schema helper - Public folder images use
/paths (unoptimized) - Pass imported images as props, not paths