{"record":{"id":"54c2792129d833be","repo":"withastro/astro","slug":"getimagenotusedonserver","errorCode":"GetImageNotUsedOnServer","errorMessage":"`getImage()` should only be used on the server. To use images on the client, render the `src` from `getImage()` during the server render, then pass it to the client for usage.","messagePattern":"`getImage\\(\\)` should only be used on the server\\. To use images on the client, render the `src` from `getImage\\(\\)` during the server render, then pass it to the client for usage\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/assets/vite-plugin-assets.ts","lineNumber":224,"sourceCode":"\t\t\t},\n\t\t\tload: {\n\t\t\t\tfilter: {\n\t\t\t\t\tid: new RegExp(`^(${RESOLVED_VIRTUAL_MODULE_ID}|${RESOLVED_VIRTUAL_GET_IMAGE_ID})$`),\n\t\t\t\t},\n\t\t\t\thandler(id) {\n\t\t\t\t\tif (id === RESOLVED_VIRTUAL_GET_IMAGE_ID) {\n\t\t\t\t\t\t// Lightweight module exporting only getImage + imageConfig.\n\t\t\t\t\t\t// No component references (Image, Picture, Font) to avoid TDZ\n\t\t\t\t\t\t// errors when the content runtime and component pages are\n\t\t\t\t\t\t// bundled into the same prerender chunk (see #16036).\n\t\t\t\t\t\tconst isServerEnvironment = isAstroServerEnvironment(this.environment);\n\t\t\t\t\t\tconst getImageExport = isServerEnvironment\n\t\t\t\t\t\t\t? `${RUNTIME_LOGGER_SETUP}\n\t\t\t\t\t\t\t\timport { getImage as getImageInternal } from \"astro/assets\";\n\t\t\t\t\t\t\t\texport const getImage = async (options) => await getImageInternal(options, imageConfig, _runtimeLogger);`\n\t\t\t\t\t\t\t: `import { AstroError, AstroErrorData } from \"astro/errors\";\n\t\t\t\t\t\t\t\texport const getImage = async () => {\n\t\t\t\t\t\t\t\t\tthrow new AstroError(\n\t\t\t\t\t\t\t\t\t\tAstroErrorData.GetImageNotUsedOnServer.message,\n\t\t\t\t\t\t\t\t\t\tAstroErrorData.GetImageNotUsedOnServer.hint,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t};`;\n\n\t\t\t\t\t\tconst assetQueryParams = settings.adapter?.client?.assetQueryParams\n\t\t\t\t\t\t\t? `new URLSearchParams(${JSON.stringify(\n\t\t\t\t\t\t\t\t\tArray.from(settings.adapter.client.assetQueryParams.entries()),\n\t\t\t\t\t\t\t\t)})`\n\t\t\t\t\t\t\t: 'undefined';\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcode: `\n\t\t\t\t\t\t\t\texport const imageConfig = ${JSON.stringify(settings.config.image)};\n\t\t\t\t\t\t\t\tObject.defineProperty(imageConfig, 'assetQueryParams', {\n\t\t\t\t\t\t\t\t\tvalue: ${assetQueryParams},\n\t\t\t\t\t\t\t\t\tenumerable: false,\n\t\t\t\t\t\t\t\t\tconfigurable: true,","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/assets/vite-plugin-assets.ts#L206-L242","documentation":"Astro exposes `getImage()` through a virtual module that is environment-aware. When that module is bundled for the client, `getImage` is replaced by a stub that throws GetImageNotUsedOnServer at call time (vite-plugin-assets.ts:189). Image optimization is a server-side operation; calling it in browser-executed code is unsupported.","triggerScenarios":"Importing `getImage` (virtual:get-image / astro:assets re-export) inside a hydrated component, client script, or framework component that ships to the browser, then calling it there; a shared utility used by both server pages and client islands that calls getImage at module scope or in an event handler.","commonSituations":"Refactoring a .astro page into a React/Preact/Svelte island and moving the getImage call along with it; calling getImage inside onClick/useEffect; library code that assumed Node always executes it.","solutions":["Move the `getImage()` call into server-executed code (.astro frontmatter, endpoints, SSR components) and pass the resulting `src`/attributes down as props","If a shared helper must exist, branch on `import.meta.env.SSR` and only call getImage on the server branch","For client-driven images, use plain <img> with a URL the server already prepared"],"exampleFix":"// before (client island)\nimport { getImage } from 'astro/assets';\nconst img = await getImage({ src: hero }); // throws in browser\n\n// after (server component passes result down)\n// Server.astro: const img = await getImage({ src: hero });\n// <Island imgSrc={img.src} imgAttrs={img.attributes} />","handlingStrategy":"validation","validationCode":"// keep getImage out of client bundles by branching on the environment\nexport async function safeGetImage(options) {\n  if (!import.meta.env.SSR) {\n    throw new Error('safeGetImage must only be called during server rendering');\n  }\n  const { getImage } = await import('astro/assets');\n  return getImage(options);\n}","typeGuard":"function isServerRender(): boolean {\n  return import.meta.env.SSR === true;\n}","tryCatchPattern":"try {\n  const img = await getImage(options);\n} catch (err) {\n  if (err instanceof AstroError && err.code === 'GetImageNotUsedOnServer') {\n    throw new Error('Move this getImage() call to .astro frontmatter or an API route');\n  }\n  throw err;\n}","preventionTips":["Never import getImage in files that are hydrated (islands, client entries)","Compute image URLs at build/SSR time and pass them to client components as props"],"tags":["astro","images","client-server","ssr","bundling"],"backgroundTag":"server-only-function-called-on-client","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-09-09T03:35:40.650Z","contentChangedAt":"2026-09-09T03:35:40.650Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}