withastro/astro · error · Error
Astro components cannot be used in the browser. Tried to ren
Error message
Astro components cannot be used in the browser.
Tried to render "${filename}". What it means
Thrown at runtime (in dev) when an Astro component (`.astro`) is imported into client-side code. Astro components are server-rendered; they cannot run in the browser. The plugin detects imports of `.astro` files in the client environment and returns a stub module that throws this error when the stub default export is invoked in dev, or an empty object in production builds.
Source
Thrown at packages/astro/src/vite-plugin-astro/index.ts:273
exclude: [specialQueriesRE, /(?:\?|&)astro(?:&|=|$)/],
},
},
async handler(source, id) {
const parsedId = parseAstroRequest(id);
if (!parsedId.filename.endsWith('.astro')) {
return;
}
const filename = normalizePath(parsedId.filename);
// If an Astro component is imported in code used on the client, we return an empty
// module so that Vite doesn’t bundle the server-side Astro code for the client.
if (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
return {
code: `export default import.meta.env.DEV
? () => {
throw new Error(
'Astro components cannot be used in the browser.\\nTried to render "${filename}".'
);
}
: {};`,
moduleType: 'ts',
meta: { vite: { lang: 'ts' } },
};
}
const transformResult = await compile(source, filename);
const astroMetadata: AstroPluginMetadata['astro'] = {
// Remove Astro components that have been mistakenly given client directives
// We'll warn the user about this later, but for now we'll prevent them from breaking the build
clientOnlyComponents: transformResult.clientOnlyComponents.filter(notAstroComponent),
hydratedComponents: transformResult.hydratedComponents.filter(notAstroComponent),
serverComponents: transformResult.serverComponents,
scripts: transformResult.scripts,View on GitHub (pinned to d081033d5f)
Solutions
- Move the shared logic/constants into a plain `.ts` or `.js` module and import that from both the component and the client script.
- If you need client-side interactivity, use a framework component (React/Vue/Svelte/Solid) with `client:*` directives instead of an `.astro` file.
- If you only needed types, import the type via `import type` (erased at runtime) or define types in a separate `.d.ts`.
Example fix
// before — client.ts
import MyComponent from '../components/MyComponent.astro';
// after
import { sharedConstants } from '../utils/shared.ts'; Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure no .astro import appears in client-resolved modules. // Run: grep -rn "from '.*\\.astro'" src/ then verify each importer is server-only.
Type guard
// ESLint rule of thumb: disallow importing .astro from files under src/scripts or client entrypoints. // no-restricted-syntax: reject ImportDeclaration whose source ends with .astro in client contexts.
Prevention
- Never import .astro files from client scripts; extract shared logic to .ts.
- Use framework components (React/Vue) for client interactivity, not .astro.
- Add an ESLint rule banning .astro imports outside of other .astro files.
When it happens
Trigger: Importing a `.astro` component from a `<script>` block (client-side), a client-side `.ts`/`.js` file, or any module resolved by the `client` Vite environment. The throw happens when the default export (a render function) is called in dev.
Common situations: Trying to use an Astro component as a client-side widget or web component. Importing a shared `.astro` layout/component from a client script for its types or constants. Confusing Astro components (server-only) with framework components (React/Vue/Svelte) which can hydrate.
Related errors
- ServerOnlyModule
- <script src="${src}"> references an asset in the "${public
- ActionCalledFromServerError
- Configured image service is not a local service
- FontFileUrlNotFound
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/7a3725dfacd6a466.
Report an issue: GitHub.