withastro/astro · error · AstroError
ServerOnlyModule
ServerOnlyModule
Error message
The "astro:config/server" module is only available server-side.
What it means
The virtual module `astro:config/server` exposes the Astro config to server-side code (it reads the serialized manifest). It only exists in server environments; when it is resolved from the client environment the manifest Vite plugin throws ServerOnlyModule, meaning you imported `astro:config/server` (directly or transitively) into browser-bound code. Use `astro:config/client` there - it inlines only the public subset of config values.
Solutions
- Switch the import to `astro:config/client` in browser-reachable code.
- Split shared config helpers into server and client variants so server config never enters the client graph.
- Pass needed config values from server components as props instead of importing the server module in client code.
Example fix
// before - client-bundled module
import { config } from 'astro:config/server';
// after
import { config } from 'astro:config/client'; Defensive patterns
Strategy: type-guard
Type guard
// in shared code: pick the right virtual module for the environment
const getConfig = import.meta.env.SSR
? () => import('astro:config/server')
: () => import('astro:config/client'); Prevention
- Use astro:config/client in any module that can be bundled for the browser.
- Keep server-config reads in files only imported by endpoints, middleware, or server components.
- Pass config values as props from server components instead of importing the server module in client code.
When it happens
Trigger: Importing astro:config/server inside an inline `<script>` tag or a `client:*` component; a shared utility module that reads config and is imported by both server endpoints and client scripts; importing it in a static page's client bundle.
Common situations: Wanting base/trailingSlash config in client-side navigation helpers and grabbing the wrong module; refactors that move a config-reading helper into a shared file; SSR-to-static migrations pulling formerly server-only imports into the client graph.
Related errors
- i18nNotEnabled
- ServerOnlyModule
- You need to enable the `prefetch` Astro config to import…
- Apps must be an object with an id, a name and an entrypoint.
- [astro] deprecated. Move onto your processor instead (e.g…
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/886b17f8c8fe97fc.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/manifest/virtual-module.ts:88
return RESOLVED_VIRTUAL_CLIENT_ID;
}
},
},
load: {
filter: {
id: new RegExp(`^(${RESOLVED_VIRTUAL_SERVER_ID}|${RESOLVED_VIRTUAL_CLIENT_ID})$`),
},
handler(id) {
if (id === RESOLVED_VIRTUAL_CLIENT_ID) {
// astro:config/client inlines values directly from settings instead of
// importing from virtual:astro:manifest to avoid pulling server-only
// virtual modules (virtual:astro:routes, virtual:astro:pages) into the
// client environment where they are not available.
return { code: clientConfigCode };
}
if (id === RESOLVED_VIRTUAL_SERVER_ID) {
if (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
throw new AstroError({
...AstroErrorData.ServerOnlyModule,
message: AstroErrorData.ServerOnlyModule.message(VIRTUAL_SERVER_ID),
});
}
const code = `
import { manifest } from '${SERIALIZED_MANIFEST_ID}'
import { fromRoutingStrategy } from "astro/app";
let i18n = undefined;
if (manifest.i18n) {
i18n = {
defaultLocale: manifest.i18n.defaultLocale,
locales: manifest.i18n.locales,
routing: fromRoutingStrategy(manifest.i18n.strategy, manifest.i18n.fallbackType),
fallback: manifest.i18n.fallback,
domains: manifest.i18n.domains,
};
}View on GitHub (pinned to 52e6c34790)