-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Description
Astro Info
Astro v5.16.5
Node v22.21.1
System Linux (x64)
Package Manager yarn
Output static
Adapter none
Integrations none
Description
When @assets points to a directory outside the project root (one level up), images imported from it and rendered via astro:assets (either <Image> or getImage) fail in dev with a 500 from the /_image endpoint.
The same images, when used via a plain <img src={asset.src}>, work fine in dev.
Build (astro build) also works: the generated HTML references hashed files under /_astro/... and loads correctly.
So the problem appears to be specific to the dev image service when @assets points to an external directory outside the project root.
Minimal reproduction
-
Create a fresh Astro project:
npm create astro@latest mainsite -- --template minimal --install --no-git --skip-houston
-
Make
shared-assetsas an external to the project directory:
mkdir shared-assets
cat > shared-assets/logo.svg << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 200 60">
<rect width="100%" height="100%" fill="none"/>
<circle cx="30" cy="30" r="20" fill="#1f8ceb"/>
<path d="M46 22 L62 30 L46 38 Z" fill="#0b6abf" opacity="0.9"/>
<text x="90" y="36" font-family="sans-serif"
font-size="20" fill="#111" dominant-baseline="middle">Astro</text>
</svg>
EOF- Create a test PNG file (yellow square 256x256):
base64 -d > shared-assets/square.png << 'EOF'
iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC
AdnJLH8AAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAf1JREFU
eNrt0zENAAAIwDAOFCIeO3CjgVbCkmVPBXyVEmAAMAAYAAwABgADgAHAAGAAMAAYAAwABgADgAHA
AGAAMAAYAAwABgADgAHAAGAAMAAYAAwABgADgAHAAGAAMAAYAAwABgADgAHAAGAAMAAYAAwABgAD
gAHAAGAAMAAYAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOA
AcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAMAAYAA4AB
wABgADAAGAAMAAYAA4ABwABgADAAGAAMAAYAA4ABwABgADAAGAAMAAYAA4ABwABgADAAGAAMAAYA
A4ABwABgADAAGAAMAAYAA4ABwABgADAAGAAMAAYAA2AAMAAYAAwABgADgAHAAGAAMAAYAAwABgAD
gAHAAGAAMAAYAAwABgADgAHAAGAAMAAYAAwABgADgAHAAGAAMAAYAAwABgADgAHAAGAAMAAYAAwA
BgADgAHAAGAAMAAYAAyAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAG
AAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAPAteHUBihHS2lg
AAAAAElFTkSuQmCC
EOF- Make sure Vite is allowed to read outside the project root, i.e. in
astro.config.mjs:
cat > mainsite/astro.config.mjs << 'EOF'
import { defineConfig } from "astro/config";
import { fileURLToPath } from "node:url";
// Resolve alias paths
const assetsPath = fileURLToPath(new URL("../shared-assets", import.meta.url));
export default defineConfig({
vite: {
resolve: {
alias: {
"@assets": assetsPath,
},
},
server: {
fs: {
allow: ['.', '../..'],
},
},
},
});
EOF- In
src/pages/index.astroadd an image imported from@assetsand rendered viaastro:assets:
cat > mainsite/src/pages/index.astro << 'EOF'
---
import { Image, getImage } from "astro:assets";
import logo from "@assets/logo.svg";
import square from "@assets/square.png";
---
<html>
<body>
<!-- This SVG goes through /_image -->
<Image src={logo} width={140} alt="SVG logo via astro:assets" />
<!-- This SVG uses Vite /@fs and works -->
<img src={logo.src} width="140" alt="SVG logo via img src" />
<br/>
<!-- This PNG goes through /_image -->
<Image src={square} width={256} alt="PNG square via astro:assets" />
<!-- This PNG uses Vite /@fs and works -->
<img src={square.src} width="256" alt="PNG square via img src" />
</body>
</html>
EOF- Run dev server:
(cd mainsite && clear && npm run dev -- --verbose --host)- Open the page in the browser and check the Network tab.
Expected behavior
- Every image loads successfully in dev.
- The
<Image>(orgetImage) call uses the/_imageendpoint without errors, even though@assetsreference an external directory.
Actual behavior
When item is logo or square:
-
The
<img src={<item>.src}>version works in dev. -
The
<Image src={<item>}>/getImage({ src: <item> })version fails:-
The browser requests something like:
<img src="/_image?href=%2F%40fs%2Ftmp%2Ft2%2Fshared-assets%2Flogo.svg%..."
-
The dev server responds with 500 for that /_image request.
-
-
No such problem in
astro buildoutput: the generated HTML references a static file under/_astro/...and it loads correctly (tested withnpm run build && npm run preview -- --host).
So the behavior is inconsistent:
- dev + external
@assets+astro:assets→ 500 from /_image - dev + external
@assets+ plain<img src={asset.src}>→ OK - build + external
@assets+astro:assets→ OK
Environment
- Astro: 5.16.5
- Node: v22.21.1
- Npm: 10.9.4
- OS: Linux (also likely reproducible on other OSes as well)
Additional context
- In my real project,
@assetswould be a reference to a shared assets folder in the parent workspace (monorepo). - Dev server already allows going up via
vite.server.fs.allow = ['.', '../..']. - The broken dev URL encodes a path under /@fs/tmp/t2/shared-assets/logo.svg into the href query parameter of /_image, which seems to trip whatever path/FS checks the image service uses.
- Using
<img src={asset.src}>everywhere is a viable workaround, but it would be great ifastro:assetsworked with assets located in an upper-level directory (via alias) in dev the same way it does in build. - The issue seems to be strongly related with the astro:assets image service returns 500 in dev when src/assets is a symlink #14937
What's the expected result?
- Each image loads successfully in dev.
- The
<Image>(orgetImage) call uses the/_imageendpoint without errors, even though@assetsreference an external directory.
N.B. stackblitz does not allow to create parent dirs, so there is a ER app there
Link to Minimal Reproducible Example
yarn install
yarn workspace mainsite dev