withastro/astro · error · AstroError
ActionNotFoundError
ActionNotFoundError
Error message
The server received a request for an action named `${actionName}` but could not find a match. If you renamed an action, check that you've updated your `actions/index` file and your calling code to match. What it means
An `ActionNotFoundError` thrown during action path traversal when an intermediate path segment resolves to a function before all keys are consumed. Actions are leaf nodes — once the traversal reaches a function, it cannot go deeper. For example, requesting `foo.bar` when `foo` is already an action function triggers this. The guard is `if (typeof server === 'function')` inside the key loop.
Source
Thrown at packages/astro/src/core/base-pipeline.ts:380
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('.')),
});
}
if (!Object.hasOwn(server, key)) {
throw new AstroError({
...ActionNotFoundError,
message: ActionNotFoundError.message(pathKeys.join('.')),
});
}
// @ts-expect-error we are doing a recursion... it's ugly
server = server[key];View on GitHub (pinned to d081033d5f)
Solutions
- Check that the action path doesn't traverse through an existing leaf action name.
- Rename the conflicting action or namespace so they don't overlap.
- Run `astro check` to detect mismatched action names.
- Ensure `Astro.callAction` uses the correct dotted path matching your `server` export structure.
Example fix
// before — src/actions/index.ts
export const server = {
login: defineAction({ handler: async () => { ... } }), // leaf
};
// calling Astro.callAction('login.google') → error
// after
export const server = {
login: {
password: defineAction({ handler: async () => { ... } }),
google: defineAction({ handler: async () => { ... } }),
},
}; Defensive patterns
Strategy: validation
Validate before calling
function isValidActionPath(server: object, path: string): boolean {
let current: unknown = server;
for (const key of path.split('.')) {
if (typeof current === 'function') return false; // hit a leaf too early
if (!Object.hasOwn(current as object, key)) return false;
current = (current as Record<string, unknown>)[key];
}
return typeof current === 'function';
} Try / catch
try {
await Astro.callAction('users.delete', input);
} catch (e) {
if (e instanceof Error && e.name === 'ActionNotFoundError') {
console.error('Action path invalid:', e.message);
}
throw e;
} Prevention
- Keep action namespacing flat or clearly nested — don't mix leaf and branch names.
- Use TypeScript types from astro:actions to get compile-time path checking.
- Document the action tree structure for callers.
When it happens
Trigger: `getAction('parent.child')` is called. During traversal, `server` is reassigned to `server['parent']` which is a function. On the next iteration for `'child'`, the `typeof server === 'function'` check fires and `ActionNotFoundError` is thrown with the full dotted path.
Common situations: Calling a nested action path where the parent is a flat action (e.g. `Astro.callAction('login.google')` when `login` is itself a function). A client sends a fabricated action path. Renaming/refactoring actions creates a naming collision where a namespace name is also an action name.
Related errors
- [astro:actions] `defineAction()` unexpectedly used on the cl
- [astro:actions] `getActionContext()` unexpectedly used on th
- BAD_REQUEST
- ActionCalledFromServerError
- Action not found: ${path}
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/b85f7d38ed69f811.
Report an issue: GitHub.