diff --git a/.changeset/happy-fireants-occur.md b/.changeset/happy-fireants-occur.md
new file mode 100644
index 000000000000..40ffcf4c6cf7
--- /dev/null
+++ b/.changeset/happy-fireants-occur.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Improve error handling when an Astro component is rendered manually
diff --git a/packages/astro/src/core/errors/errors-data.ts b/packages/astro/src/core/errors/errors-data.ts
index 0b74ca6752a5..5a2b75cabd2f 100644
--- a/packages/astro/src/core/errors/errors-data.ts
+++ b/packages/astro/src/core/errors/errors-data.ts
@@ -415,6 +415,20 @@ See https://docs.astro.build/en/guides/server-side-rendering/ for more informati
},
hint: 'Mutable values declared at runtime are not supported. Please make sure to use exactly `export const prerender = true`.',
},
+ /**
+ * @docs
+ * @message
+ * **Example error messages:**
+ * InvalidComponentArgs: Invalid arguments passed to component.
+ * @description
+ * Astro components cannot be rendered manually via a function call, such as `Component()` or `{items.map(Component)}`. Prefer the component syntax `` or `{items.map(item => )}`.
+ */
+ InvalidComponentArgs: {
+ title: 'Invalid component arguments.',
+ code: 3020,
+ message: (name: string) => `Invalid arguments passed to${name ? ` <${name}>` : ''} component.`,
+ hint: 'Astro components cannot be rendered directly via function call, such as `Component()` or `{items.map(Component)}`.',
+ },
// Vite Errors - 4xxx
UnknownViteError: {
title: 'Unknown Vite Error.',
diff --git a/packages/astro/src/runtime/server/astro-component.ts b/packages/astro/src/runtime/server/astro-component.ts
index 933a69a9a67a..975be7054acb 100644
--- a/packages/astro/src/runtime/server/astro-component.ts
+++ b/packages/astro/src/runtime/server/astro-component.ts
@@ -1,11 +1,28 @@
import type { PropagationHint } from '../../@types/astro';
import type { AstroComponentFactory } from './render/index.js';
+import { AstroError, AstroErrorData } from '../../core/errors/index.js';
-function baseCreateComponent(cb: AstroComponentFactory, moduleId?: string) {
+function validateArgs(args: unknown[]): args is Parameters {
+ if (args.length !== 3) return false;
+ if (!args[0] ||typeof args[0] !== 'object') return false;
+ return true;
+}
+function baseCreateComponent(cb: AstroComponentFactory, moduleId?: string): AstroComponentFactory {
+ const name = moduleId?.split('/').pop()?.replace('.astro', '') ?? ''
+ const fn = (...args: Parameters) => {
+ 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
- cb.isAstroComponentFactory = true;
- cb.moduleId = moduleId;
- return cb;
+ fn.isAstroComponentFactory = true;
+ fn.moduleId = moduleId;
+ return fn;
}
interface CreateComponentOptions {