Environment
@imagekit/astro 1.0.1
astro 6.4.5
output: 'static'
Summary
In static builds, ImageKit-path srcs passed to <Image /> are never turned into ImageKit URLs.
Dev behaves as documented; astro build instead routes every image through Astro's build-time generation, emits a local /_astro/... URL, and fails with ENOENT because the source file doesn't exist locally.
Reproduction
// astro.config.mjs
import { defineConfig } from "astro/config"
import imagekit from "@imagekit/astro/integration"
export default defineConfig({
integrations: [imagekit({ urlEndpoint: "https://ik.imagekit.io/<id>" })],
})
---
import { Image } from "astro:assets"
---
<Image src="/some-folder/photo.jpg" width={800} height={600} alt="test" />
(/some-folder/photo.jpg exists in the ImageKit media library, not locally.)
Dev output (correct):
<img src="https://ik.imagekit.io/<id>/some-folder/photo.jpg?tr=c-at_max,w-800" ...>
Build output (wrong), followed by a hard failure:
<img src="/_astro/photo_1u4BnC.jpg" ...>
Error generating image for /some-folder/photo.jpg:
ENOENT: no such file or directory, open '<project>/dist/some-folder/photo.jpg'
Root cause
The service registers sharp's transform/parseURL hooks for non-ImageKit srcs, so Astro core's isLocalService() classifies it as a local service.
In prerendered builds, getImage() (astro/dist/assets/internal.js, the isLocalService(service) && globalThis.astroAsset.addStaticImage branch) then re-routes every non-http(s) src into addStaticImage(), discarding the URL getURL() returned and queueing local generation that reads from dist/ — hence the ENOENT. The dev/SSR /_image endpoint flow never hits this branch, which is why dev works.
Full https://ik.imagekit.io/... srcs are also affected: getURL() returns a transformed URL different from the src, so they fail the initialImageURL === validatedOptions.src escape hatch and get downloaded and re-optimized locally by sharp instead of being served from the CDN.
Expected behaviour
Static builds should emit the same ImageKit CDN URLs as dev/SSR for fast-path srcs.
Workaround
Bypass astro:assets and build URLs directly with buildSrc from @imagekit/javascript in a custom component.
Environment
@imagekit/astro1.0.1astro6.4.5output: 'static'Summary
In static builds, ImageKit-path srcs passed to
<Image />are never turned into ImageKit URLs.Dev behaves as documented;
astro buildinstead routes every image through Astro's build-time generation, emits a local/_astro/...URL, and fails withENOENTbecause the source file doesn't exist locally.Reproduction
(
/some-folder/photo.jpgexists in the ImageKit media library, not locally.)Dev output (correct):
Build output (wrong), followed by a hard failure:
Root cause
The service registers sharp's
transform/parseURLhooks for non-ImageKit srcs, so Astro core'sisLocalService()classifies it as a local service.In prerendered builds,
getImage()(astro/dist/assets/internal.js, theisLocalService(service) && globalThis.astroAsset.addStaticImagebranch) then re-routes every non-http(s)src intoaddStaticImage(), discarding the URLgetURL()returned and queueing local generation that reads fromdist/— hence theENOENT. The dev/SSR/_imageendpoint flow never hits this branch, which is why dev works.Full
https://ik.imagekit.io/...srcs are also affected:getURL()returns a transformed URL different from the src, so they fail theinitialImageURL === validatedOptions.srcescape hatch and get downloaded and re-optimized locally by sharp instead of being served from the CDN.Expected behaviour
Static builds should emit the same ImageKit CDN URLs as dev/SSR for fast-path srcs.
Workaround
Bypass
astro:assetsand build URLs directly withbuildSrcfrom@imagekit/javascriptin a custom component.