withastro/astro · error · AstroError

RemoteImageNotAllowed

RemoteImageNotAllowed

Error message

Remote image ${url} is not allowed by your image configuration.

What it means

When your Astro config defines `image.domains` or `image.remotePatterns`, every remote image must match one of them before Astro will fetch it. `isRemoteAllowed(url, allowlistConfig)` returning false at remoteProbe.ts:47 throws RemoteImageNotAllowed — this is a deliberate SSRF/asset-hygiene guard, not a bug.

Solutions

  1. Add the host to `image.domains: ['cdn.partner.com']` in astro.config.mjs for a simple allowlist
  2. Or add a matching `image.remotePatterns` entry with protocol/hostname/pathname fields covering the URL
  3. Double-check pattern details: hostname must match exactly (or wildcard), pathname needs to match the asset path (default '/**' style globs), scheme must match

Example fix

// before (astro.config.mjs)
image: { domains: ['old-cdn.com'] }

// after
image: {
  domains: ['old-cdn.com', 'cdn.partner.com'],
  remotePatterns: [{ protocol: 'https', hostname: '**.partner.com' }],
}
Defensive patterns

Strategy: validation

Validate before calling

// mirror Astro's allowlist check before using a remote image
function isRemoteAllowed(url: string, cfg: { domains?: string[]; remotePatterns?: Array<{ protocol?: string; hostname: string | string[]; pathname?: string }> }): boolean {
  try {
    const u = new URL(url);
    if (cfg.domains?.includes(u.hostname)) return true;
    return (cfg.remotePatterns ?? []).some((p) => {
      if (p.protocol && p.protocol !== u.protocol.replace(':', '')) return false;
      const hostOk = Array.isArray(p.hostname) ? p.hostname.includes(u.hostname) : u.hostname === p.hostname || (p.hostname.startsWith('**.') && u.hostname.endsWith(p.hostname.slice(2)));
      return hostOk;
    });
  } catch {
    return false;
  }
}
if (!isRemoteAllowed(src, imageConfig)) throw new Error(`Remote image not allowed: ${src}`);

Try / catch

try {
  const size = await inferRemoteSize(url, imageConfig);
} catch (err) {
  if (err instanceof AstroError && err.code === 'RemoteImageNotAllowed') {
    // collect violations and report to content owners instead of failing the build cold
    reportDisallowedImage(url);
    return null;
  }
  throw err;
}

Prevention

When it happens

Trigger: `<Image src="https://cdn.partner.com/logo.png" />` when cdn.partner.com is not listed; adding a new CDN or CMS media host without updating config; remotePatterns regex/protocol/host fields that do not match the actual URL (pattern written for http while image is https, or missing pathname glob).

Common situations: Migrating CMS image domains; staging vs production hosts both needing entries; writing a remotePattern that accidentally excludes the exact asset path; forgetting the config only affects remote (http) images.

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/8ca20189ee37862f. Report an issue: GitHub.

Appendix: source

Thrown at packages/astro/src/assets/utils/remoteProbe.ts:47

	const allowlistConfig = imageConfig
		? {
				domains: imageConfig.domains ?? [],
				remotePatterns: imageConfig.remotePatterns ?? [],
			}
		: undefined;

	if (!allowlistConfig) {
		const parsedUrl = new URL(url);
		if (!['http:', 'https:'].includes(parsedUrl.protocol)) {
			throw new AstroError({
				...AstroErrorData.FailedToFetchRemoteImageDimensions,
				message: AstroErrorData.FailedToFetchRemoteImageDimensions.message(url),
			});
		}
	}

	if (allowlistConfig && !isRemoteAllowed(url, allowlistConfig)) {
		throw new AstroError({
			...AstroErrorData.RemoteImageNotAllowed,
			message: AstroErrorData.RemoteImageNotAllowed.message(url),
		});
	}

	// Start fetching the image with redirect validation
	let response: Response;
	try {
		response = await fetchWithRedirects({
			url,
			onMaxRedirectsExceeded: (u) =>
				new AstroError({
					...AstroErrorData.FailedToFetchRemoteImageDimensions,
					message: AstroErrorData.FailedToFetchRemoteImageDimensions.message(u),
				}),
			onMissingLocationHeader: (_status, u) =>
				new AstroError({
					...AstroErrorData.FailedToFetchRemoteImageDimensions,

View on GitHub (pinned to 52e6c34790)