ComposioHQ/composio · error · ComposioInvalidModifierError

Invalid beforeExecute modifier. Not a function.

Error message

Invalid beforeExecute modifier. Not a function.

What it means

ComposioInvalidModifierError thrown when the beforeExecute modifier provided to Tools.execute (or the modifiers config) is present but not a function. This is a config/type validation error, not a runtime API failure.

Source

Thrown at ts/packages/core/src/models/Tools.ts:294

      tool,
      { toolSlug, toolkitSlug, params },
      modifiers?.beforeFileUpload,
      requestOptions
    );

    // apply the before execute modifiers
    if (modifiers?.beforeExecute) {
      if (typeof modifiers.beforeExecute === 'function') {
        modifiedParams = await modifiers.beforeExecute({
          toolSlug,
          toolkitSlug,
          params: modifiedParams,
        });
        if (requestOptions?.signal?.aborted) {
          throw new ComposioRequestCancelledError();
        }
      } else {
        throw new ComposioInvalidModifierError('Invalid beforeExecute modifier. Not a function.');
      }
    }
    return modifiedParams;
  }

  /**
   * Applies schema-aware file preprocessing shared by direct and Tool Router
   * session execution. This always runs before the caller's `beforeExecute`
   * hook so the hook observes the exact arguments sent to the backend.
   */
  private async applyFileUploadModifiers(
    tool: Tool,
    {
      toolSlug,
      toolkitSlug,
      params,
    }: {
      toolSlug: string;

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Pass a function: modifiers: { beforeExecute: async ({ params }) => ({ ...params, extra: 1 }) }.
  2. If using TypeScript, remove any/as any so the compiler catches the wrong shape.
  3. If no pre-execution transformation is needed, omit beforeExecute entirely.

Example fix

// before
await tools.execute('T', params, { beforeExecute: { enabled: true } as any });

// after
await tools.execute('T', params, { beforeExecute: async ({ params }) => params });
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof modifiers?.beforeExecute !== 'function') throw new TypeError('beforeExecute must be a function');
await tools.execute(slug, params, modifiers);

Type guard

const isValidBeforeExecute = (m: unknown): m is (args: any) => any | Promise<any> =>
  typeof m === 'function';

Try / catch

try { ... } catch (e) {
  if (e instanceof ComposioInvalidModifierError) { /* fix modifier shape and retry */ }
}

Prevention

When it happens

Trigger: Passing modifiers.beforeExecute as an object, string, or undefined-but-truthy value, e.g. { beforeExecute: { params: {...} } } or a class instance without call signature.

Common situations: Confusing the modifier argument shapes (passing config object instead of function); serializing modifiers accidentally; JS users bypassing type checks with as any.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/87f565a881439f70. Report an issue: GitHub.