withastro/astro · error · AstroError

NoClientOnlyHint

NoClientOnlyHint

Error message

Unable to render `${componentName}`. When using the `client:only` hydration strategy, Astro needs a hint to use the correct renderer.

What it means

A `client:only` component was used, but the hint value (`metadata.hydrateArgs`) does not match any known framework/renderer. Because `client:only` skips server rendering, Astro cannot guess the renderer, so it throws `NoClientOnlyHint` suggesting the probable framework names (e.g. `react|preact|vue|svelte|solid`).

Source

Thrown at packages/astro/src/runtime/server/render/component.ts:218

				: metadata.hydrateArgs;
			if (clientOnlyValues.has(rendererName)) {
				// throw an error if provide correct client:only directive but not find the renderer
				const plural = validRenderers.length > 1;
				throw new AstroError({
					...AstroErrorData.NoMatchingRenderer,
					message: AstroErrorData.NoMatchingRenderer.message(
						metadata.displayName,
						metadata?.componentUrl?.split('.').pop(),
						plural,
						validRenderers.length,
					),
					hint: AstroErrorData.NoMatchingRenderer.hint(
						formatList(probableRendererNames.map((r) => '`' + r + '`')),
					),
				});
			} else {
				// throw an error if an invalid hydration directive was provided
				throw new AstroError({
					...AstroErrorData.NoClientOnlyHint,
					message: AstroErrorData.NoClientOnlyHint.message(metadata.displayName),
					hint: AstroErrorData.NoClientOnlyHint.hint(
						probableRendererNames.map((r) => r.replace('@astrojs/', '')).join('|'),
					),
				});
			}
		} else if (typeof Component !== 'string') {
			const matchingRenderers = validRenderers.filter((r) =>
				probableRendererNames.includes(r.name),
			);
			const plural = validRenderers.length > 1;
			if (matchingRenderers.length === 0) {
				throw new AstroError({
					...AstroErrorData.NoMatchingRenderer,
					message: AstroErrorData.NoMatchingRenderer.message(
						metadata.displayName,
						metadata?.componentUrl?.split('.').pop(),

View on GitHub (pinned to d081033d5f)

Solutions

  1. Provide a valid framework hint matching an installed renderer: `client:only="react"`, `"preact"`, `"vue"`, `"svelte"`, `"solid-js"`.
  2. Check spelling of the hint against the error's suggested list.
  3. For a custom renderer, use the exact renderer `name` as the hint.

Example fix

// before
<Widget client:only="raect" />

// after
<Widget client:only="react" />
Defensive patterns

Strategy: validation

Validate before calling

const CLIENT_ONLY_HINTS = ['react', 'preact', 'vue', 'svelte', 'solid-js'];
function assertClientOnlyHint(hint: unknown): asserts hint is string {
  if (typeof hint !== 'string' || !CLIENT_ONLY_HINTS.includes(hint)) {
    throw new Error(`Invalid client:only hint '${String(hint)}'. Use one of: ${CLIENT_ONLY_HINTS.join(', ')}`);
  }
}

Type guard

const isValidClientOnlyHint = (hint: unknown): hint is string =>
  typeof hint === 'string' && CLIENT_ONLY_HINTS.includes(hint);

Prevention

When it happens

Trigger: `client:only` with no value at all; `client:only="raect"` typo; `client:only="jquery"` for a framework with no integration; value referencing a package name instead of the short framework key.

Common situations: Typing the framework name incorrectly; forgetting the hint entirely; using a custom renderer name that doesn't match the registered renderer's name.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/0e3c6ffd3d8d99fb. Report an issue: GitHub.