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

client:only components are never server-rendered, so Astro needs the value of the directive to pick the client renderer. When the value is missing or not a recognized framework name (not in react, preact, vue, svelte, solid-js after alias resolution), NoClientOnlyHint is thrown with a hint listing valid values derived from your probable renderers.

Solutions

  1. Add the framework value: <Comp client:only="react" /> (or preact, vue, svelte, solid)
  2. For solid use client:only="solid" (aliased internally to solid-js)
  3. If using a non-bundled renderer, check its docs for the exact hint string it registers

Example fix

// before
<Widget client:only />

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

Strategy: validation

Validate before calling

const VALID_HINTS = new Set(['react', 'preact', 'vue', 'svelte', 'solid']);
if (!VALID_HINTS.has(hint)) {
  throw new Error('client:only needs one of: ' + [...VALID_HINTS].join(', '));
}

Type guard

function isClientOnlyHint(value: unknown): value is string {
  return typeof value === 'string' && ['react', 'preact', 'vue', 'svelte', 'solid'].includes(value);
}

Prevention

When it happens

Trigger: A bare <Comp client:only /> or client:only={true}; client:only="alpine" or another unsupported framework string; a typo like client:only="reactt"; using a renderer whose name does not match any known alias.

Common situations: Copying bare client:only from old docs or examples; assuming Astro infers the framework from the file extension (it does not for client:only); switching frameworks and forgetting to update the hint.

Related errors


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

Appendix: 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 52e6c34790)