withastro/astro · error · AstroError

InvalidComponentArgs

InvalidComponentArgs

Error message

Invalid arguments passed to <${name}> component.

What it means

Every compiled .astro component is wrapped by baseCreateComponent, whose wrapper validates the call shape before delegating: exactly 3 arguments (props, slots, children) with props as a non-null object. The Astro renderer and compiler always call components with that shape, so a failure means the component factory was invoked outside the normal rendering contract. This is almost always direct programmatic invocation rather than JSX rendering.

Solutions

  1. Render the component through JSX (<Component {...props} />) or through the supported programmatic API (experimental_AstroContainer from astro/container) instead of calling the factory by hand
  2. If you must invoke the factory, pass all three arguments: Component(props, slots, children) with props as an object
  3. Fix any wrapper/HOC to forward the full argument list: (...args) => factory(...args)
  4. Check for isAstroComponentFactory(fn) before treating a module export as a callable render function

Example fix

// before
const html = await Component({ name: 'x' });

// after
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
const container = await AstroContainer.create();
const html = await container.renderToString(Component, { props: { name: 'x' } });
Defensive patterns

Strategy: type-guard

Validate before calling

import { isAstroComponentFactory } from 'astro/runtime/server/index.js';

if (!isAstroComponentFactory(Component)) {
  throw new TypeError('Not an Astro component factory');
}

Type guard

function isCallableAstroComponent(fn: unknown): fn is (...args: any[]) => any {
  return typeof fn === 'function' && (fn as any).isAstroComponentFactory === true;
}

Prevention

When it happens

Trigger: Calling an .astro component factory directly: Component() with no args, Component({x:1}) with only props (args.length !== 3), or Component('title') passing a primitive as the first argument (typeof args[0] !== 'object'). Also triggered by wrappers/HOCs that forward a reduced argument list, e.g. (props) => factory(props).

Common situations: Rendering .astro components programmatically in unit tests or scripts instead of through JSX; utility functions that call component factories manually; custom renderers or integrations that invoke Astro components with an invented signature; code migrated from older internal APIs.

Related errors


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

Appendix: source

Thrown at packages/astro/src/runtime/server/astro-component.ts:18

import { AstroError, AstroErrorData } from '../../core/errors/index.js';
import type { PropagationHint } from '../../types/public/internal.js';
import type { AstroComponentFactory } from './render/index.js';

function validateArgs(args: unknown[]): args is Parameters<AstroComponentFactory> {
	if (args.length !== 3) return false;
	if (!args[0] || typeof args[0] !== 'object') return false;
	return true;
}
function baseCreateComponent(
	cb: AstroComponentFactory,
	moduleId?: string,
	propagation?: PropagationHint,
): AstroComponentFactory {
	const name = moduleId?.split('/').pop()?.replace('.astro', '') ?? '';
	const fn = (...args: Parameters<AstroComponentFactory>) => {
		if (!validateArgs(args)) {
			throw new AstroError({
				...AstroErrorData.InvalidComponentArgs,
				message: AstroErrorData.InvalidComponentArgs.message(name),
			});
		}
		return cb(...args);
	};
	Object.defineProperty(fn, 'name', { value: name, writable: false });
	// Add a flag to this callback to mark it as an Astro component
	fn.isAstroComponentFactory = true;
	fn.moduleId = moduleId;
	fn.propagation = propagation;
	return fn;
}

interface CreateComponentOptions {
	factory: AstroComponentFactory;
	moduleId?: string;
	propagation?: PropagationHint;

View on GitHub (pinned to 52e6c34790)