withastro/astro · error · Error
Configured image service is not a local service
Error message
Configured image service is not a local service
What it means
Same 'transform' guard as the generic dev endpoint, but in the shared handleImageRequest used across adapters/build paths. It calls getConfiguredImageService() and requires a LocalImageService; an external service (no transform) throws a plain Error.
Source
Thrown at packages/astro/src/assets/endpoint/shared.ts:45
}
return Buffer.from(await res.arrayBuffer());
} catch {
return undefined;
}
}
export const handleImageRequest = async ({
request,
loadLocalImage,
}: {
request: Request;
loadLocalImage: (src: string, baseUrl: URL) => Promise<Buffer | undefined>;
}) => {
const imageService = await getConfiguredImageService();
if (!('transform' in imageService)) {
throw new Error('Configured image service is not a local service');
}
const url = new URL(request.url);
const transform = await imageService.parseURL(url, imageConfig);
if (!transform?.src) {
return new Response('Invalid request', { status: 400 });
}
// Reject requests that attempt to convert a non-SVG source to SVG output.
// This mirrors the same guard in verifyOptions() that protects the <Image> component path.
if (transform.format === 'svg') {
const sourceFormat = inferSourceFormat(transform.src);
if (sourceFormat !== 'svg') {
return new Response('Cannot convert non-SVG source to SVG format', { status: 403 });
}
}
View on GitHub (pinned to d081033d5f)
Solutions
- Configure a local service (e.g. sharp) for paths that go through handleImageRequest.
- For external/CDN services, rely on URL generation and avoid the local optimization handler.
- Ensure a custom service implements transform.
Example fix
// before - external service for an SSR build that hits the shared handler
image: { service: passthroughImageService }
// after
image: { service: sharpImageService } Defensive patterns
Strategy: validation
Validate before calling
// Before relying on handleImageRequest, confirm the configured service is local.
import { isLocalService } from 'astro/assets';
const svc = await getConfiguredImageService();
if (!isLocalService(svc)) throw new Error('Shared image handler requires a local service.'); Type guard
function isLocalImageService(s: any): boolean {
return s && typeof s === 'object' && typeof s.transform === 'function';
} Prevention
- Configure a local service (sharp) for SSR/build paths using handleImageRequest.
- Use external services only for URL generation, not local optimization.
- Implement transform in any custom service.
When it happens
Trigger: An adapter or build/hybrid path that routes image requests through handleImageRequest while an external image service is configured.
Common situations: SSR adapter + external service where the shared handler is invoked; build-time optimization expecting a local service; custom service missing transform.
Related errors
- Configured image service is not a local service
- Incorrect transform returned by `parseURL`
- MissingGetFontFileRequestUrl
- [preview] No adapter found.
- SessionStorageInitError
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/cf8df9c57707f344.
Report an issue: GitHub.