-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Description
Astro Info
Astro v5.16.3
Vite v6.4.1
Node v22.21.1
System Linux (x64)
Package Manager npm
Output static
Adapter none
Integrations none
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
Description
When src/assets is a symlink, 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 + symlinked src/assets.
Minimal reproduction
-
Create a fresh Astro project (any template is fine):
npm create astro@latest my-app -- --template minimal --install --no-git --skip-houston
-
Make
src/assetsas a symlink:
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
(cd my-app/src && ln -s ../../shared-assets assets)- Make sure Vite is allowed to read outside the project root if needed, e.g. in
astro.config.mjs:
cat > my-app/astro.config.mjs << 'EOF'
import { defineConfig } from "astro/config";
export default defineConfig({
vite: {
server: {
fs: {
allow: ['.', '../..'],
},
},
},
});
EOF- In
src/pages/index.astroadd an image imported fromsrc/assetsand rendered viaastro:assets:
cat > my-app/src/pages/index.astro << 'EOF'
---
import { Image, getImage } from "astro:assets";
import logo from "../assets/logo.svg";
---
<html>
<body>
<!-- This one goes through /_image -->
<Image src={logo} width={140} alt="logo via astro:assets" />
<!-- This one uses Vite /@fs and works -->
<img src={logo.src} width="140" alt="logo via img src" />
</body>
</html>
EOF- Run dev server:
(cd my-app && npm run dev -- --host 0.0.0.0)- Open the page in the browser and check the Network tab.
Expected behavior
- Both images load successfully in dev.
- The
<Image>(orgetImage) call uses the/_imageendpoint without errors, even thoughsrc/assetsis a symlink.
Actual behavior
-
The
<img src={logo.src}>version works in dev. -
The
<Image src={logo}>/getImage({ src: logo })version fails:-
The browser requests something like:
<img src="/_image?href=%2F%40fs%2Ftmp%2Ft%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.
So the behavior is inconsistent:
- dev + symlinked
src/assets+astro:assets→ 500 from /_image - dev + symlinked
src/assets+ plain<img src={asset.src}>→ OK - build + symlinked
src/assets+astro:assets→ OK
Environment
- Astro: 5.16.3
- Node: v22.21.1
- Npm: 10.9.4
- OS: Linux (symlinks on ext4; also likely reproducible on other Unix-like systems)
Additional context
- In my real project,
src/assetsis a symlink to a shared assets folder in a sibling workspace (monorepo). - Dev server already allows going up via
vite.server.fs.allow = ['.', '../..']. - The broken dev URL encodes a path under /@fs/.../src/assets/... 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 if astro:assets worked with symlinked src/assets 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 @assets points to ext. dir #14957
What's the expected result?
- Both images load successfully in dev.
- The
<Image>(orgetImage) call uses the/_imageendpoint without errors, even thoughsrc/assetsis a symlink.
N.B. stackblitz does not allow to create symlinks, so there is a ER app there
Link to Minimal Reproducible Example
Participation
- I am willing to submit a pull request for this issue.