unstale

npm / next-safe-action

next-safe-action

What changed in next-safe-action 8, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-22.

12 breaking2 security5 deprecations8 new APIs and options5 behavior and defaults18 fixes and other

See which of these apply to your code, ranked, in your agent:

npx @unstale/cli init

@unstale/cli 0.2.2 on npm

next-safe-action 850 changes

Breaking changes 12

  • Queued dispatches marked stale by reset() no longer call the action or write to the server; their executeAsync promises resolve with {} and their callbacks do not fire. Applies to useStateAction and useOptimisticStateAction.

    8.7.1release notes

  • Adds an optimistic hook for stateful actions. Dispatches queue, each receives the previous result, and optimistic updates can accumulate instead of using last-write-wins behavior.

    8.7.0release notes

  • Output schema transforms and defaults are applied to returned data and the onSuccess callback, rather than using the raw action return value.

    8.6.0release notes

  • In useAction and useOptimisticAction, reset() invalidates in-flight executions so pending responses cannot repopulate hook state.

    8.6.0release notes

  • All hooks report idle status immediately after reset, even while an uncancellable in-flight execution is still settling.

    8.6.0release notes

  • Passing a non-JSON-serializable payload now throws a clear error instead of leaking a raw TypeError.

    8.5.5release notes

  • The library no longer has deepmerge-ts as a runtime dependency; it now ships with zero runtime dependencies.

    8.5.3release notes

  • Action results now prioritize validationErrors, then serverError, then data, so only one of these fields is populated when multiple errors occur.

    8.5.0release notes

  • The transitioning value was removed from the HookActionStatus union; the isTransitioning boolean on the hook return object is unchanged.

    8.5.0release notes

  • Hook return types are now discriminated unions keyed on status; utilities such as Pick, Omit, and Partial distribute over the union, and constructed values must match one branch.

    8.5.0release notes

  • Callbacks now fire immediately after an action completes.

    8.1.2release notes

  • Navigation errors are thrown immediately to support Next.js Cache Components.

    8.1.1release notes

Security 2

  • Validation issue paths are traversed safely, and hostile keys are stored as own properties so they cannot modify the global prototype.

    8.5.5release notes

  • Field keys are assigned safely to prevent hostile keys from modifying the global prototype.

    8.5.5release notes

Deprecations 5

  • Renames the exported type SafeActionUtils; SafeActionUtils remains available as a deprecated alias.

    8.1.9release notes

  • Renames the exported type HookSafeActionFn; HookSafeActionFn remains available as a deprecated alias.

    8.1.9release notes

  • Renames the exported type HookSafeStateActionFn; HookSafeStateActionFn remains available as a deprecated alias.

    8.1.9release notes

  • Renames the exported type StateServerCodeFn; StateServerCodeFn remains available as a deprecated alias.

    8.1.9release notes

  • Renames the exported type DVES; DVES remains available as a deprecated alias.

    8.1.9release notes

New APIs and options 8

  • Adds an option to useAction and useOptimisticAction that seeds the hook with an initial result; reset() restores it.

    8.6.0release notes

  • Adds a utility for returning typed, expected server errors to the client as result.serverError, bypassing handleServerError.

    8.6.0release notes

  • Adds post-validation middleware with type-safe context.

    8.4.0release notes

  • Adds a flag to internal hooks, defaulting to false; when true, navigation functions such as forbidden() and notFound() navigate to an error page, and onNavigation and onSettled callbacks cannot be used.

    8.2.0release notes

  • Exported from the core package so developers can use it.

    8.1.10release notes

  • Exported from the core package so developers can use it.

    8.1.10release notes

  • Exported from the core package so developers can use it.

    8.1.10release notes

  • The inputSchema method now provides access to clientInput.

    8.1.0release notes

Behavior and default changes 5

  • Confirmed state uses successful action data when available, otherwise currentState; a revalidated currentState can supersede an in-flight dispatch result.

    8.7.0release notes

  • Validation and server errors roll back to the last confirmed domain state, and failed dispatches pass that state as prevResult.data to keep queued writes based.

    8.7.0release notes

  • useStateAction supports overlapping executeAsync invocations, with each promise settling with its own execution result.

    8.6.0release notes

  • SafeActionResult is now a discriminated union: checking data, serverError, or validationErrors narrows the other fields to undefined.

    8.5.0release notes

  • Structured inputs are now extracted from schemas instead of being derived by iterating client inputs.

    8.1.4release notes

Fixes and other changes 18

  • In useAction, useOptimisticAction, and useStateAction, onNavigation and onSettled now fire exactly once for a single redirect.

    8.7.3release notes

  • Stops leaking an unhandled promise rejection when the action call itself rejects; the error still reaches the caller through status, onError with thrownError, and the executeAsync rejection.

    8.7.2release notes

  • Stops leaking an unhandled promise rejection when the action call itself rejects; the error still reaches the caller through status, onError with thrownError, and the executeAsync rejection.

    8.7.2release notes

  • When currentState commits mid-queue, payloads from already-settled dispatches stop being applied again, preventing optimistic state from duplicating changes.

    8.7.1release notes

  • A currentState arriving while an action is running no longer discards that action’s data when building the next queued dispatch’s server base; the result follows write order.

    8.7.1release notes

  • A raw thrown error now settles promises for dispatches queued behind it; previously React clearing the action queue could leave those promises unresolved.

    8.7.0release notes

  • A throw from a dispatch made stale by reset no longer cancels fresh queued work.

    8.7.0release notes

  • A synchronous throw from a user callback no longer escapes before dispatch enqueueing, which could leave executeAsync pending forever.

    8.7.0release notes

  • When an action is dispatched inside a React transition, dispatch-time state now also applies from a microtask so it can commit immediately; this fixes pending status, input visibility, and callback timing in the action hooks.

    8.6.1release notes

  • Results resolving to undefined are normalized where stored, preventing onSuccess and onSettled from firing again on unrelated re-renders.

    8.6.1release notes

  • In useStateAction, reset() marks already-dispatched executions stale so they cannot clear reset state, consume the initResult baseline, or repopulate errors.

    8.6.0release notes

  • When called inside a Next.js 'use cache' scope with cacheComponents enabled, validation errors are returned as validationErrors instead of a generic server error.

    8.5.5release notes

  • Hook callbacks now fire once per action execution instead of replaying on every restore from the Next.js router bfcache.

    8.5.4release notes

  • The deprecation notice was removed from the hook.

    8.3.0release notes

  • The hook's code was fixed.

    8.3.0release notes

  • Reverses the _errors/object check order and skips _errors keys as nested objects.

    8.1.9release notes

  • Rapid execute or executeAsync calls now update UI state only from the latest request, preventing a slower earlier response from overwriting a later result; pre-transition state updates are synchronous.

    8.1.9release notes

  • Checks ActionServerValidationError before the serverErrorHandled guard.

    8.1.5release notes