Fix: Action Not Found in Astro

Error message:
Action not found.
Actions 2025-01-25

What Causes This Error?

This error occurs when you try to call an action that doesn’t exist. This typically happens due to typos, incorrect imports, or missing action definitions.

The Problem

---
import { actions } from 'astro:actions';
---

<script>
  import { actions } from 'astro:actions';

  // ❌ Action 'subscrbe' doesn't exist (typo)
  const result = await actions.subscrbe({ email: 'test@example.com' });
</script>
// src/actions/index.ts
export const server = {
  subscribe: defineAction({
    // Action is named 'subscribe', not 'subscrbe'
  }),
};

The Fix

Use Correct Action Name

<script>
  import { actions } from 'astro:actions';

  // ✅ Correct spelling
  const result = await actions.subscribe({ email: 'test@example.com' });
</script>

Common Scenarios

TypeScript Autocomplete

// TypeScript will catch typos at compile time
import { actions } from 'astro:actions';

// ✅ IDE shows available actions
actions.subscribe  // Autocomplete shows this
actions.subscrbe   // TypeScript error: Property doesn't exist

Define Actions Properly

// src/actions/index.ts
import { defineAction, z } from 'astro:actions';

// Actions must be exported as 'server'
export const server = {
  subscribe: defineAction({
    input: z.object({
      email: z.string().email(),
    }),
    handler: async ({ email }) => {
      return { success: true };
    },
  }),

  unsubscribe: defineAction({
    input: z.object({
      email: z.string().email(),
    }),
    handler: async ({ email }) => {
      return { success: true };
    },
  }),
};

Check File Location

# Actions must be in correct location
src/
├── actions/
│   └── index.ts    ✅ Correct location

├── action/
│   └── index.ts    ❌ Wrong folder name

└── actions.ts      ❌ Wrong (needs to be in folder)

Export Named ‘server’

// ❌ Wrong export name
export const actions = {
  subscribe: defineAction({ /* ... */ }),
};

// ❌ Default export doesn't work
export default {
  subscribe: defineAction({ /* ... */ }),
};

// ✅ Must be named 'server'
export const server = {
  subscribe: defineAction({ /* ... */ }),
};

Nested Actions

// src/actions/index.ts
export const server = {
  // Nested structure
  user: {
    create: defineAction({ /* ... */ }),
    delete: defineAction({ /* ... */ }),
  },
  newsletter: {
    subscribe: defineAction({ /* ... */ }),
    unsubscribe: defineAction({ /* ... */ }),
  },
};
// Calling nested actions
import { actions } from 'astro:actions';

await actions.user.create({ name: 'John' });
await actions.newsletter.subscribe({ email: 'test@example.com' });

// ❌ Wrong path
await actions.create({ name: 'John' });  // Missing 'user' namespace

Restart Dev Server

# Sometimes you need to restart after adding actions
npm run dev

# Or clear the cache
rm -rf node_modules/.astro
npm run dev

Check Import Statement

// ✅ Correct import
import { actions } from 'astro:actions';

// ❌ Wrong import paths
import { actions } from '../actions';
import { actions } from 'astro/actions';
import { actions } from '@astro/actions';

Form Action Attribute

---
import { actions } from 'astro:actions';
---

<!-- ✅ Use action directly -->
<form method="POST" action={actions.subscribe}>
  <input type="email" name="email" />
  <button type="submit">Subscribe</button>
</form>

<!-- ❌ Wrong - using string -->
<form method="POST" action="/api/subscribe">
  ...
</form>

Debug Available Actions

// Log available actions
import { actions } from 'astro:actions';

console.log('Available actions:', Object.keys(actions));

Common Typos

// Watch for these common mistakes
actions.subcribe     // subscribe
actions.unsubcribe   // unsubscribe
actions.delelte      // delete
actions.create       // createUser
actions.login        // signin

Quick Checklist

  • Check action name spelling
  • Actions must be in src/actions/index.ts
  • Export as server, not actions or default
  • Use import { actions } from 'astro:actions'
  • Restart dev server after adding actions
  • Check for nested action paths