# Safe Action Advanced

> Use when working with bind arguments, metadata schemas, framework errors (redirect/notFound/forbidden/unauthorized), type inference utilities (InferSafeActionFnInput/Result), or server-level action callbacks

- Skill: `om-scogo/safe-action-advanced` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds add om-scogo/safe-action-advanced`
- Raw SKILL.md: https://api.skillmd.com/api/skills/om-scogo/safe-action-advanced/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: om-scogo (https://skillmd.com/u/om-scogo)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/om-scogo/safe-action-advanced

---


# next-safe-action Advanced Features

## Overview

| Feature | Use Case |
|---|---|
| [Bind arguments](./bind-arguments.md) | Pass extra args to actions via `.bind()` (e.g., resource IDs) |
| [Metadata](./metadata.md) | Attach typed metadata to actions for use in middleware |
| [Framework errors](./framework-errors.md) | Handle redirect, notFound, forbidden, unauthorized in actions |
| [Type utilities](./type-utilities.md) | Infer types from action functions and middleware |

## Server-Level Action Callbacks

The second argument to `.action()` accepts callbacks that run **on the server** (not client-side hooks):

```ts
export const createPost = authActionClient
  .inputSchema(schema)
  .action(
    async ({ parsedInput, ctx }) => {
      const post = await db.post.create(parsedInput);
      return post;
    },
    {
      onSuccess: async ({ data, parsedInput, ctx, metadata, clientInput }) => {
        // Runs on the server after successful execution
        await invalidateCache("posts");
      },
      onError: async ({ error, metadata, ctx, clientInput, bindArgsClientInputs }) => {
        // error: { serverError?, validationErrors? }
        await logError(error);
      },
      onSettled: async ({ result }) => {
        // Always runs
        await recordMetrics(result);
      },
      onNavigation: async ({ navigationKind }) => {
        // Runs when a framework error (redirect, notFound, etc.) occurs
        console.log("Navigation:", navigationKind);
      },
    }
  );
```

These are distinct from hook callbacks (`useAction({ onSuccess })`) — server callbacks run in the Node.js runtime, hook callbacks run in the browser.

## throwServerError

Re-throw server errors instead of returning them as `result.serverError`:

```ts
export const myAction = actionClient
  .inputSchema(schema)
  .action(serverCodeFn, {
    throwServerError: true,
    // The handled server error (return of handleServerError) is thrown
  });
```

