Actions
Call external services or perform non-transactional Convex work with reactive operation state.
Use a Convex action for work that cannot run inside a query or mutation, such as calling a third-party API.
const { run: generateSummary, pending: generating } = useConvexAction(api.ai.generateSummary)
const result = await generateSummary({ documentId })Mutation or action
| Work | Use |
|---|---|
| Read Convex data | Query |
| Transactionally write Convex data | Mutation |
| Call an external API | Action |
| Schedule durable Convex work | Mutation/action plus Convex scheduler as appropriate |
| Hold a Nuxt-only secret | Nitro server route |
Do not use an action for ordinary database writes. Actions are not transactional across their external effects.
State and control flow
useConvexAction returns run and the same state as useConvexMutation:
statuspendingdataerrorreset()
run resolves with the action result and rejects with a ConvexCallError that carries the action path in functionName.
import { isConvexCallError } from '@lupinum/better-convex-nuxt/errors'
const { run: sendInvite, pending: sending } = useConvexAction(api.email.sendInvite)
async function invite() {
try {
await sendInvite({ email: email.value })
toast.success('Invitation sent')
} catch (error) {
toast.error(isConvexCallError(error) ? error.message : 'Invitation failed')
}
}A server error message is the text that the Convex function put in ConvexError data. Library failures use fixed messages.
Progress
The composable tracks whether the action call is pending. It does not provide step-by-step action progress.
For long workflows, write progress to Convex data and observe that data with a query. The action remains the worker; the query becomes the observable product state.
Retries
An action may have completed an external side effect before its response fails. Design idempotency into external calls and do not retry unknown failures blindly.
Like mutations, an action call rejects with IDENTITY_CHANGED when the signed-in user changes before it finishes. Its result never appears in the new user's state.