#onSuccess issue with CustomAction

5 messages · Page 1 of 1 (latest)

summer shoalBOT
#

Hi @lime oyster. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

It looks like you’re running into TypeScript errors related to the use of an onSuccess property in your customAction's input return value. Based on the error messages and your code, the issue is that the customAction (from convex-helpers/server/customFunctions) does not expect or support an onSuccess property in the object returned from the input function.

What’s Happening?

The customAction, customQuery, and customMutation helpers from convex-helpers allow you to modify the context (ctx) and arguments (args) passed to your Convex functions, but they do not support an onSuccess callback in the way you’re attempting. The object you return from input should only contain ctx and args (and any additional fields you want to inject into the context or arguments), but not lifecycle hooks like onSuccess.

This is confirmed by the error message:

Property 'onSuccess' does not exist on type '{ args: {}; ctx: {}; }'.

And by the examples in the docs and community threads, which only show returning ctx and args (and sometimes additional injected values), but never onSuccess or similar hooks.

How to Log After Success?

If you want to log after the action completes, you should do so in the handler itself, not via an onSuccess property in the context. For example:

#
export const userAction = customAction(
  action,
  {
    args: {
      userId: v.optional(v.id("users")),
    },
    input: async (ctx, args) => {
      const identity = await ctx.auth.getUserIdentity();
      if (!identity) {
        throw new Error("Called without authentication present");
      }
      const user = await ctx.runQuery(internal.users.getUserIdentity, {
        tokenIdentifier: identity.tokenIdentifier,
      });
      if (!user) throw new Error("Authentication required");
      return {
        ctx: { user },
        args,
      };
    },
  }
);

// In your handler, log after the main logic:
export const someAction = userAction({
  args: { /* ... */ },
  handler: async (ctx, args) => {
    // ... your action logic ...
    const result = /* ... */;
    console.info(`Action for user ${ctx.user.name} returned:`, result);
    return result;
  },
});

About Circular Type Issues

The circular type inference errors you’re seeing are a known issue in Convex when you use ctx.runQuery or ctx.runMutation and return their results without explicitly typing the handler’s return value. The recommended fix is to explicitly type the return value of your handler or the result of the runQuery/runMutation call. See the official guidance here: Dealing with circular type inference.

Summary

  • The onSuccess property is not supported in the return value of input for customAction/customQuery/customMutation.
  • Do your logging or post-processing in the handler itself.
  • For circular type errors, explicitly type your handler’s return value or the result of runQuery/runMutation.
#

If you need to inject user data into the context, your current approach (returning { ctx: { user }, args } from input) is correct, but keep all post-processing in the handler.

If you have further issues with types, consider reviewing the TypeScript best practices for Convex and the circular inference workaround.

If you need more advanced middleware-like behavior, see the custom functions documentation for patterns that are supported.


If you have more specific needs for lifecycle hooks, you may need to implement them manually in your handler, as Convex’s current custom function helpers do not support such hooks natively.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@lime oyster Kapa.ai is still learning and improving, please let me know how I did by reacting below.