withastro/astro · error · Error
You tried to add the ${name} client renderer, but its server
Error message
You tried to add the ${name} client renderer, but its server renderer wasn't added. You must add the server renderer first. Use the `addServerRenderer` function. What it means
Client renderers hydrate `client:*` components in the browser, but they must be paired with a server renderer already present in the manifest. `addClientRenderer` looks up the renderer by `name` and attaches its `clientEntrypoint`; if no server renderer with that name exists, the lookup returns `-1` and the call is rejected.
Source
Thrown at packages/astro/src/container/index.ts:425
*
* const container = await AstroContainer.create();
* container.addServerRenderer(reactRenderer);
* container.addClientRenderer({
* name: "@astrojs/react",
* entrypoint: "@astrojs/react/client.js"
* });
* ```
*
* @param options {object}
* @param options.name The name of the renderer. The name **isn't** arbitrary, and it should match the name of the package.
* @param options.entrypoint The entrypoint of the client renderer.
*/
public addClientRenderer(options: AddClientRenderer): void {
const { entrypoint, name } = options;
const rendererIndex = this.#pipeline.manifest.renderers.findIndex((r) => r.name === name);
if (rendererIndex === -1) {
throw new Error(
'You tried to add the ' +
name +
" client renderer, but its server renderer wasn't added. You must add the server renderer first. Use the `addServerRenderer` function.",
);
}
const renderer = this.#pipeline.manifest.renderers[rendererIndex];
renderer.clientEntrypoint = entrypoint;
this.#pipeline.manifest.renderers[rendererIndex] = renderer;
}
// NOTE: we keep this private via TS instead via `#` so it's still available on the surface, so we can play with it.
// @ts-expect-error @ematipico: I plan to use it for a possible integration that could help people
private static async createFromManifest(
manifest: SSRManifest,
): Promise<experimental_AstroContainer> {
const container = new experimental_AstroContainer({
manifest,View on GitHub (pinned to d081033d5f)
Solutions
- Call `addServerRenderer` with the same `name` before `addClientRenderer`.
- Verify the `name` strings match exactly (usually the integration package name, e.g. `@astrojs/react`).
- If rendering server-only components, you can skip `addClientRenderer` entirely.
Example fix
// before
container.addClientRenderer({ name: '@astrojs/react', entrypoint: '@astrojs/react/client.js' });
// after
container.addServerRenderer(reactRenderer);
container.addClientRenderer({ name: '@astrojs/react', entrypoint: '@astrojs/react/client.js' }); Defensive patterns
Strategy: validation
Validate before calling
const has = container['#pipeline'].manifest.renderers.some(r => r.name === name);
if (!has) throw new Error(`Add server renderer ${name} first`); Type guard
function serverRendererRegistered(manifest, name) {
return manifest.renderers.some(r => r.name === name);
} Prevention
- Always call `addServerRenderer` before `addClientRenderer` with matching names.
- Keep a single source of truth for the renderer name string.
When it happens
Trigger: Calling `container.addClientRenderer({ name, entrypoint })` before the matching `container.addServerRenderer(...)` for the same `name`.
Common situations: Reversing the documented add-server-then-add-client order; name mismatch (e.g. server registered as `'@astrojs/react'` but client passed as `'react'`); forgetting to call `addServerRenderer` at all when using `AstroContainer.create()` from a minimal manifest.
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
- NoMatchingRenderer
- NoClientOnlyHint
- Unable to render ${metadata.displayName}! This component li
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/1158268204a44256.
Report an issue: GitHub.