withastro/astro · error · Error
Unable to render ${metadata.displayName}! This component li
Error message
Unable to render ${metadata.displayName}!
This component likely uses ${formatList(probableRendererNames)},
but Astro encountered an error during server-side rendering.
Please ensure that ${metadata.displayName}:
1. Does not unconditionally access browser-specific globals like `window` or `document`.
If this is unavoidable, use the `client:only` hydration directive.
2. Does not conditionally return `null` or `undefined` when rendered on the server.
3. If using multiple JSX frameworks at the same time (e.g. React + Preact), pass the correct `include`/`exclude` options to integrations.
If you're still stuck, please open an issue on GitHub or join us at https://astro.build/chat. What it means
The ambiguous-multiple-renderers branch: more than one renderer's name matched the component, so Astro picked one and called its `ssr.renderToStaticMarkup`, but the SSR render itself failed (threw or returned no markup). This is a generic catch-all guiding you to the most common SSR failure causes rather than a specific AstroError code.
Source
Thrown at packages/astro/src/runtime/server/render/component.ts:256
validRenderers.length,
),
hint: AstroErrorData.NoMatchingRenderer.hint(
formatList(probableRendererNames.map((r) => '`' + r + '`')),
),
});
} else if (matchingRenderers.length === 1) {
// We already know that renderer.ssr.check() has failed
// but this will throw a much more descriptive error!
renderer = matchingRenderers[0];
({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call(
{ result },
Component,
propsWithoutTransitionAttributes,
children,
metadata,
));
} else {
throw new Error(`Unable to render ${metadata.displayName}!
This component likely uses ${formatList(probableRendererNames)},
but Astro encountered an error during server-side rendering.
Please ensure that ${metadata.displayName}:
1. Does not unconditionally access browser-specific globals like \`window\` or \`document\`.
If this is unavoidable, use the \`client:only\` hydration directive.
2. Does not conditionally return \`null\` or \`undefined\` when rendered on the server.
3. If using multiple JSX frameworks at the same time (e.g. React + Preact), pass the correct \`include\`/\`exclude\` options to integrations.
If you're still stuck, please open an issue on GitHub or join us at https://astro.build/chat.`);
}
}
} else {
if (metadata.hydrate === 'only') {
html = await renderSlotToString(result, slots?.fallback);
} else {
const componentRenderStartTime = performance.now();View on GitHub (pinned to d081033d5f)
Solutions
- Guard browser-global access behind `if (typeof window !== 'undefined')` or an `import.meta.env.SSR` check.
- Switch the component to `client:only="<framework>"` if it cannot run on the server at all.
- Avoid unconditionally returning `null`/`undefined` during SSR.
- When using two JSX frameworks together, configure each integration's `include`/`exclude` so components route to the correct renderer.
Example fix
// before — component reads window at render time
export default function Map() {
const w = window.innerWidth; // throws during SSR
return <canvas width={w} />;
}
// after — guard, or render client-only
import Map from './Map.tsx';
<Map client:only="react" /> Defensive patterns
Strategy: try-catch
Validate before calling
// Guard browser globals before they're accessed const isBrowser = typeof window !== 'undefined'; const width = isBrowser ? window.innerWidth : 0;
Type guard
const canSSR = (Comp: unknown): boolean => {
// best-effort: only SSR components that don't need browser globals at import time
try { return typeof Comp === 'function'; } catch { return false; }
}; Try / catch
// Sandbox SSR of a risky component and fall back to client:only
let html: string | null = null;
try {
html = renderToStringSSR(Risky);
} catch (e) {
// log and skip SSR; render with client:only instead
} Prevention
- Gate all browser-global access behind `import.meta.env.SSR` / `typeof window` checks.
- Use `client:only` for components that fundamentally can't SSR.
- Configure `include`/`exclude` on JSX integrations when running two frameworks.
When it happens
Trigger: Component unconditionally reads `window`/`document`/`localStorage` during module evaluation or render; the component conditionally returns `null`/`undefined`; multiple JSX integrations (React + Preact) are active and resolving to the wrong one; the framework component throws internally during SSR.
Common situations: Browser-only libraries (charts, maps, editors) imported into an SSR'd component; React/Preact confusion when both are installed; components that render `null` until a client effect runs.
Related errors
- The renderer you passed isn't valid. A renderer is usually a
- The renderer name must be provided when adding a server rend
- You tried to add the ${name} client renderer, but its server
- Unable to render ${displayName} because it is ${Component}!
- ActionCalledFromServerError
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/4c9ef6911fc6dddc.
Report an issue: GitHub.