withastro/astro · error · AstroError
RemoteImageNotAllowed
RemoteImageNotAllowed
Error message
Remote image ${imageURL} is not allowed by your image configuration. What it means
When `inferSize: true` is set, `getImage()` must probe the remote image to learn its dimensions (packages/astro/src/assets/internal.ts:88-94). Before fetching, it checks the URL against the `images.domains` / `images.remotePatterns` allowlist; a remote `src` that is not allowed throws `RemoteImageNotAllowed` instead of making the request.
Solutions
- Add the host to `image.domains` in `astro.config.mjs` (or a matching `image.remotePatterns` entry) and restart dev.
- Alternatively supply explicit `width`/`height` and drop `inferSize`, which keeps the URL opaque without a probe.
- Check the exact hostname in the error message against your config — scheme, subdomain, and port must all line up with `remotePatterns`.
Example fix
// astro.config.mjs — before
image: { domains: [] }
// astro.config.mjs — after
image: { domains: ['cdn.example.com'] } Defensive patterns
Strategy: validation
Validate before calling
// mirror Astro's allowlist check before calling getImage with inferSize
function isRemoteAllowed(src: string, domains: string[], remotePatterns: { hostname?: string }[]): boolean {
const host = new URL(src).hostname;
return domains.includes(host) || remotePatterns.some((p) => p.hostname === host);
}
if (opts.inferSize && !isRemoteAllowed(opts.src, image.domains, image.remotePatterns ?? [])) {
throw new Error(`Domain not allowlisted for inferSize: ${opts.src}`);
} Try / catch
try {
const img = await getImage({ src: url, inferSize: true });
} catch (err) {
if (err.name === 'RemoteImageNotAllowed') {
// fall back to explicitly sized transform, or prompt the user to allowlist the domain
} else throw err;
} Prevention
- Keep image.domains in config reviewed next to any new CDN onboarding.
- Prefer remotePatterns with explicit hostname patterns over open wildcards.
- Add a test page exercising one inferSize remote image per allowed domain.
When it happens
Trigger: `getImage({ src: 'https://cdn.example.com/hero.png', inferSize: true })` while `cdn.example.com` is absent from `image.domains` and matches no `image.remotePatterns` entry.
Common situations: Enabling `inferSize` for existing remote images without updating the image security config; new CDNs or subdomains after a migration; typos in the domain config (`www.` vs bare domain).
Related errors
- ExpectedImage
- ExpectedImageOptions
- ExpectedNotESMImage
- MissingImageDimension
- ⚠️ Astro could not optimize image
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/714b585c804201f4.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/assets/internal.ts:92
const service = await getConfiguredImageService();
// If the user inlined an import, something fairly common especially in MDX, or passed a function that returns an Image, await it for them
const resolvedOptions: ImageTransform = {
...options,
src: await resolveSrc(options.src),
};
let originalWidth: number | undefined;
let originalHeight: number | undefined;
// Infer size for remote images if inferSize is true
if (resolvedOptions.inferSize) {
delete resolvedOptions.inferSize; // Delete so it doesn't end up in the attributes
if (isRemoteImage(resolvedOptions.src) && isRemotePath(resolvedOptions.src)) {
if (!isRemoteAllowed(resolvedOptions.src, imageConfig)) {
throw new AstroError({
...AstroErrorData.RemoteImageNotAllowed,
message: AstroErrorData.RemoteImageNotAllowed.message(resolvedOptions.src),
});
}
const getRemoteSize = (url: string) =>
service.getRemoteSize?.(url, imageConfig, logger) ?? inferRemoteSize(url, imageConfig);
const result = await getRemoteSize(resolvedOptions.src); // Directly probe the image URL
resolvedOptions.width ??= result.width;
resolvedOptions.height ??= result.height;
// We've already paid for the fetch; reuse it to pin down the output format so the URL
// (and any baked filename) doesn't have to defer or refetch.
if (result.format) {
resolvedOptions.format ??= resolveDefaultOutputFormat(result.format);
}
originalWidth = result.width;
originalHeight = result.height;
}View on GitHub (pinned to e294953aa8)