withastro/astro · error · TypeError

Expected `server` export in actions file to be an object. Re

Error message

Expected `server` export in actions file to be an object. Received ${typeof server}.

What it means

A `TypeError` thrown when the actions module's `server` export is falsy or not an object. `getAction` calls `this.getActions()` and destructures `{ server }`; if `server` is null, undefined, or a non-object type, the guard `!server || typeof server !== 'object'` triggers. This means the `src/actions/index.*` file doesn't correctly export a `server` object.

Source

Thrown at packages/astro/src/core/base-pipeline.ts:371

	}

	async getServerIslands(): Promise<ServerIslandMappings> {
		if (this.serverIslands) {
			return this.serverIslands();
		}

		return {
			serverIslandMap: new Map(),
			serverIslandNameMap: new Map(),
		};
	}

	async getAction(path: string): Promise<ActionClient<unknown, ActionAccept, $ZodType>> {
		const pathKeys = path.split('.').map((key) => decodeURIComponent(key));
		let { server } = await this.getActions();

		if (!server || !(typeof server === 'object')) {
			throw new TypeError(
				`Expected \`server\` export in actions file to be an object. Received ${typeof server}.`,
			);
		}

		for (const key of pathKeys) {
			// An action is a leaf: once resolved to a function, its own properties
			// are not part of the action namespace and cannot be traversed further.
			if (typeof server === 'function') {
				throw new AstroError({
					...ActionNotFoundError,
					message: ActionNotFoundError.message(pathKeys.join('.')),
				});
			}
			if (FORBIDDEN_PATH_KEYS.has(key)) {
				throw new AstroError({
					...ActionNotFoundError,
					message: ActionNotFoundError.message(pathKeys.join('.')),
				});

View on GitHub (pinned to d081033d5f)

Solutions

  1. Ensure `src/actions/index.ts` exports `server` as an object containing action handlers.
  2. Use the `defineActions` or correct export pattern: `export const server = { ... }`.
  3. Check for TypeScript or syntax errors in the actions file.
  4. Verify you're on the correct Astro version for your Actions API usage.

Example fix

// before — src/actions/index.ts
export const myAction = async (input) => { ... };

// after
import { defineAction } from 'astro:actions';
export const server = {
  myAction: defineAction({
    input: z.string(),
    handler: async (input) => { ... },
  }),
};
Defensive patterns

Strategy: type-guard

Validate before calling

import type { server } from './src/actions/index';
// TypeScript will error if 'server' is missing or wrong type at build time

Type guard

function isValidServerExport(server: unknown): server is Record<string, unknown> {
  return typeof server === 'object' && server !== null && !Array.isArray(server);
}

Prevention

When it happens

Trigger: The actions file (`src/actions/index.ts`) either doesn't export `server`, exports it as a non-object (function, string, etc.), or the module failed to load and `server` is undefined. `getAction` is called (e.g. via `Astro.callAction` or RPC), destructures `{ server }`, and the typeof check fails.

Common situations: The actions file exports actions at the top level instead of nested under `server`. Using the old Actions API format after upgrading. The actions file has a syntax error causing it to export nothing. An integration or custom setup replaces the actions module incorrectly.

Related errors


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