About safe-action-advanced
Advanced next-safe-action features for configuring server actions, handling framework errors, and working with typed metadata and inferred types. It is intended for developers who need action-level controls beyond the basic action flow.
Key features
- 01Bind extra arguments to actions
- 02Attach typed metadata
- 03Handle framework errors
- 04Infer action and middleware types
- 05Configure server-level callbacks
Use cases
- 01Passing resource IDs to an action
- 02Making metadata available in middleware
- 03Handling redirect or authorization errors
- 04Rethrowing handled server errors
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ next-safe-action/ skills --skill safe-action-advancedAfter installing, type/safe-action-advancedin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
bind-arguments.mdframework-errors.mdmetadata.mdtype-utilities.mdDetails
From the project READMEnext-safe-action Advanced Features
Overview
| Feature | Use Case |
|---|---|
| Bind arguments | Pass extra args to actions via .bind() (e.g., resource IDs) |
| Metadata | Attach typed metadata to actions for use in middleware |
| Framework errors | Handle redirect, notFound, forbidden, unauthorized in actions |
| Type utilities | 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):
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:
export const myAction = actionClient
.inputSchema(schema)
.action(serverCodeFn, {
throwServerError: true,
// The handled server error (return of handleServerError) is thrown
});
Don't confuse this with returnServerError(): throwServerError throws the handled error (post-handleServerError) instead of returning it, while returnServerError(payload) returns a typed expected error in result.serverError, bypassing handleServerError entirely (see the safe-action-client skill's error-handling doc).